CVE-2021-44790: Code Execution on Apache via an Integer Underflow

January 25, 2022 | Trend Micro Research Team

In this excerpt of a Trend Micro Vulnerability Research Service vulnerability report, Guy Lederfein and Dusan Stevanovic of the Trend Micro Research Team detail a recent code execution vulnerability in the Apache webserver. The bug was originally discovered and reported by the researcher named Chamal. A carefully crafted request body can cause a buffer overflow in the mod_lua multipart parser, which could lead to code execution in the context of the security process. The following is a portion of their write-up covering CVE-2021-44790, with a few minimal modifications.


An integer underflow vulnerability has been reported in the mod_lua module of Apache httpd. The vulnerability is due to improper validation of the request body in the module's multipart parser, called via the r:parsebody() function in Lua scripts. A remote, unauthenticated attacker could exploit this vulnerability by sending a crafted request to the target server. Successful exploitation could lead to remote code execution under the security context of the server process, while an unsuccessful attack could lead to a denial-of-service condition.

The Vulnerability

The Apache HTTP server is the most popular webserver used on the Internet. The server is capable of being utilized with many different options and configurations. A wide variety of runtime loadable plug-in modules can be used to extend its functionality.

One of the official plug-in modules is the mod_lua module. As with all other modules, it can be compiled as a separate shared library with a “.so” extension. The purpose of this module is to allow the extension of the HTTP server with scripts written in the Lua programming language. If this module is loaded in the HTTP server configuration file, the lua-script handler can be set for files ending in “.lua”. The following demonstrates such a sample configuration:

HTTP is a request/response protocol described in RFCs 7230 - 7237 and other RFCs. A request is sent by a client to a server, which in turn sends a response back to the client. An HTTP request consists of a request line, various headers, an empty line, and an optional message body:

where CRLF represents the new line sequence Carriage Return (CR) followed by Line Feed (LF) and SP represents a space character.Parameters can be passed from the client to the server as name-value pairs in either the Request-URI, or in the message-body, depending on the Method used and Content-Type header. For example, a simple HTTP request passing a parameter named “param” with value “1”, using the GET method might look like this:

A similar request using the POST method might look like:

If there is more than one parameter/value pair, they are encoded as &-delimited name=value pairs:

        var1=value1&var2=value2&var3=value3...

The data in the Body of HTTP POST requests can be encoded using various standardized or proprietary methods. One of the standardized methods is multipart/form-data, defined in RFC 2388. Multipart/form-data is made up of multiple parts, each of which contains a Content-Disposition header. Each part is separated by a string of characters. The string of characters separating the parts is defined by the boundary keyword found on the Content-Type header line. The Content-Type must also be set to multipart/form-data. The Content-Disposition header contains a name parameter describing the form element being returned. Additional header lines may be present in each part; each line is separated by a new line sequence. The header is terminated by two consecutive new lines. The form element's data follows. The filename parameter provides a suggested filename to be used if the entity is detached and stored in a separate file.

One of the built-in functions supported by the mod_lua module is r:parsebody(). This function allows Lua scripts to parse the body of HTTP POST requests sent to the server. The function returns two Lua tables containing the parameter names and values parsed from the body. This function also supports HTTP POST requests encoded using the multipart/form-data content type.

An integer underflow vulnerability exists in the Apache HTTP server. When the mod_lua module is enabled and the r:parsebody() function is called from within a Lua script parsed by the server, the function req_parsebody() is called. This function checks if the HTTP POST request received by the server contains a Content-Type header beginning with the string "multipart/form-data; boundary=", indicating that the request body is encoded using the multipart/form-data content type. If found, the function searches for the boundary string defined in the ContentType header, saved to the multipart variable. After each match of the multipart string, the function searches for the first occurrence of two consecutive CRLF sequences, stored to the CRLF variable. If this match is found, the function searches in the following content for another occurrence of the multipart variable, stored to the end variable, indicating the end of the form element's data.

Later, the size of the form element's data is calculated by taking the end variable, subtracting the CRLF variable, then subtracting 8 (representing the two CRLF sequences before the element's data, and the CRLF and "--" characters at the end of the element's data). However, if the form element is not properly formatted, such that the end boundary string appears within less than 8 characters after the beginning of the two CRLF sequences, this subtraction would result in a negative number. The result of the subtraction is stored in a variable named vlen of type size_t. Therefore, if the subtraction results in a negative number, it will be converted into a large positive number before being stored in the vlen variable, resulting in an integer underflow. Specifically, if the subtraction results in -1, the vlen variable will contain the maximum size of size_t. Later, a buffer named buffer is allocated on the heap with a size of vlen+1. In the case described, this will result in an integer overflow, resulting in the allocation of a buffer of size 0. Later, the memcpy() function is called to copy the element's data into the buffer variable, with a size of vlen, resulting in a buffer overflow.

A remote, unauthenticated attacker could exploit this vulnerability by sending an HTTP POST request with a crafted body, encoded using the multipart/form-data content type, to the target server. Successful exploitation could lead to remote code execution under the security context of the server process, while an unsuccessful attack could lead to a denial-of-service condition.

Detection of Generic Attacks

The detection device must inspect all HTTP POST requests to URLs resolving to Lua scripts hosted on the Apache server. The detection device must then inspect the Content-Type header and check if it is set to “multipart/formdata”. If found, the detection device must inspect all instances of the boundary string from the Content-Type header in the HTTP body. For each instance of the boundary string found, the detection device must search for the first instance of two consecutive CRLF sequences following the found boundary. If found, the detection device must search for the next instance of the boundary string. If found, the detection device must calculate the number of characters between the beginning of the two consecutive CRLF sequences and the following boundary string. If the number of characters is less than 8, the traffic should be considered malicious; an attack exploiting this vulnerability is likely underway.

A sample malicious request, with 7 characters between beginning of the two consecutive CRLF sequences and the end boundary string, follows:

Note that the string matching must be performed in a case-sensitive manner

Conclusion

This bug has been patched by Apache with HTTP Server 2.4.52. They do not list any mitigating factors, so applying the update is the only method to fully address this vulnerability.

Special thanks to Guy Lederfein and Dusan Stevanovic of the Trend Micro Research Team for providing such a thorough analysis of this vulnerability. For an overview of Trend Micro Research services please visit http://go.trendmicro.com/tis/.

The threat research team will be back with other great vulnerability analysis reports in the future. Until then, follow the ZDI team for the latest in exploit techniques and security patches.