OptionsBleed – The Apache HTTP Server Now Bleeds
Found in the Apache HTTP server, CVE-2017-9798 lies in how Apache handles certain settings in its configuration files, resulting in memory leaks. This vulnerability is named OptionsBleed, based on its similarities with the Heartbleed vulnerability.
Updated on September 27, 2017, 4:00 PM PDT to add a technical analysis of the vulnerability.
A new vulnerability in the Apache HTTP server was found recently. Designated as CVE-2017-9798, this vulnerability lies in how Apache handles certain settings in its configuration files, resulting in memory leaks. This vulnerability is named OptionsBleed, based on its similarities with the Heartbleed vulnerability. Patches to Apache are now available.
What is OptionsBleed?
A use-after-free bug exists in the Apache HTTP Server when it handles certain settings in .htaccess configuration file(s). When an attacker sends an unauthenticated HTTP request with the OPTIONS method to a vulnerable Apache server, the server reveals some secret data from the memory in response to the request.
The following screenshot shows a typical response for an OPTIONS request from a vulnerable Apache HTTP Server. The highlighted part is the information leaked from the memory:
Figure 1. Memory leak resulting from OPTIONS request
As per Hanno Böck (the researcher who found this vulnerability) and Apache developer Jacob Champion, Apache supports a configuration directive Limit that restricts access to certain HTTP methods to specific users. If one sets this directive in a .htaccess file for an HTTP method that’s not globally registered with the server, the corruption occurs. We were able to reproduce this vulnerability when the value for Limit directive is set to an invalid (or custom) HTTP method in the .htaccess file.
While doing further debugging, we noticed that the OPTIONS method is not needed to exploit this bug. Any HTTP request that forces the server to send an Allow header in the response can be used to trigger the vulnerability.
One common example of this is the 501 Method Not Implemented response to a request with an unknown HTTP method. As shown in the screenshot below, when a non-vulnerable Apache HTTP Server receives an HTTP Request with an unknown method, it responds with HTTP Status code 501 and the response will have the Allow header with a list of HTTP methods supported by the server.
Figure 2. Correct HTTP 501 response
With a vulnerable server and a misconfigured .htaccess file, the same HTTP Request with an unknown method will leak parts of data from process memory in the Allow response header, as shown below.
Figure 3. Memory leak resulting from a misconfigured .htaccess file
Technical Details
The Apache web server (also known as httpd) has its own memory management library implemented in the Apache Portable Runtime API, which it uses to reserve heap memory. The APR library uses pools where memory is reserved and released. Internally, httpd maintains multiple pools—a global pool, and connection-specific pools. At the same time, httpd maintains a global variable named METHODS_REGISTRY, which is actually an apr_hash_t type from the APR library. All registered methods are stored in that variable, and as of version 2.4.26 they are:
Figure 4. Registered methods (Click to enlarge)
Note that ap_method_regisry_init() receives a pool. When httpd is starting up, the received pool is the global pool where METHODS_REGISTRY is allocated and filled with all predefined methods.
Once httpd is started, new methods can be added using the directive <LIMIT> defined in .htaccess files. When .htaccess files are read, the methods will be updated using the following at line 2275 of the following function:
Figure 5. Source code updating methods (Click to enlarge)
If one takes a closer look at the function, we can see that the method at line 2256 read from .htaccess files is allocated in the cmd->temp_pool. Later, at line 2276, it is copied to cmd->pool. When ap_method_register() is called, the global METHODS_REGISTRY residing in the global pool is updated. If cmd->pool is not in the global pool, the “method” residing at different pools will then be associated to the cmd->pool. If cmd->pool is released or cleaned, the pointer to method ends and references free memory. Any subsequent operation in METHODS_REGISTRY referring to the released memory will read free memory.
The memory leak
The leak happens when httpd builds an ALLOW header to send to the client. The ALLOW header is built in the following function:
Figure 6. Source code building the ALLOW header (Click to enlarge)
Note that in line 1056, the apr_array_pstrcat() function will take all methods from METHODS_REGISTRY and concatenate them into a final string that is returned to the client. For every element, the length of the METHOD is calculated internally using strlen (method). Because the free memory was previously allocated, there is data in this area. How much memory is copied or leaked this way? That will depend on the location of the first NULL character when strlen() is called. For example, say I have defined a LIMIT option in an .htaccess file as follows:
<LIMIT DDDDDD> <LIMIT>
Sending the request curl -sI -X OPTIONS http://{IP address}/test/index.html creates the internal list shown below. Note that the DDDDD option almost at the end of the list.
Figure 7. Internal list and HTTP response
If the request is sent again, we can see the internal list at the left (note the added \xd0) and the HTTP response to the client at right (note the OPTION 7 in the ALLOW header):
Figure 8. Internal list and HTTP response
It’s interesting to see how the method DDDDD was added to the list again. That is because once the initial memory becomes corrupted, httpd will add the method again at runtime. For example, sending the request again results in another leak:
Figure 9. HTTP response
Repeating this behavior multiple times results in the following behavior:
Conditions to create the leak
The .htaccess files are parsed for every request independently, regardless of the type. The conditions for the leak are created for every type of request—that is, to send any request that forces the server to create the ALLOW header, regardless if the request is valid or not. For example, we get the same leak if we send the following request:
curl -sI -X ANYANY http://192.168.93.207/test/index.html
Figure 10. HTTP response
How big can the leak be?
The size of the memory leak depends on multiple factors:
While the second factor has a limit, the others do not. In theory, the leak can be unlimited. In practice, there’s a high probability that a NULL character will stop the leak, but there is another factor to consider. Apache inspects the ALLOW header before returning it to the client. It is inspected by the ending character as specified in RFC 7230 section 3.2. This is done in the following code:
Figure 11. Source code for inspecting header
Once the first non-HT (horizontal tab) ASCII control character is found, the following restrictions are applied:
Figure 12. Source code for restriction
In conclusion, if the first non-HT ASCII control character is not one of either CR (carriage return), LF (line feed), or SPACE, it will block the ALLOW header from sending it to the client.
Patch Details
The patch stops supporting the <LIMIT> in .htaccess files, enforcing the use of the LIMIT directive to the http.conf file. New methods are only added when cmd->temp_pool is equal to cmd->pool and assumes that cmd->pool is the same pool from where METHODS_REGISTRY is created. This is true at the web server’s start-up. We can see the changes in lines 35-42 in the following code snippet.
Figure 13. Source code of patch
There were some inaccurate claims made about this vulnerability. One is that the leak occurs when several OPTION requests are sent to the server; the leak occurs right at the start. Neither is the OPTION request needed.
How serious is it?
In general, .htaccess files provide a way to make configuration changes on a per-directory basis instead of using the main server configuration file.
The official Apache HowTo Guide for .htaccess file says:
You should avoid using .htaccess files completely if you have access to httpd main server config file. Using .htaccess files slows down your Apache http server. Any directive that you can include in a .htaccess file is better set in a Directory block, as it will have the same effect with better performance.
Looking at the above guidelines and considering the necessary pre-conditions, OptionsBleed doesn’t appear to be a critical bug.
However, when a user does not have access to the main server configuration file, the .htaccess file can be used to set configurations specific to your website. This will be the case in typical shared web hosting environments, where ISPs do not share root access to the server system and the main server configuration file.
An attacker using a shared host can maliciously craft a .htaccess file for his own website and, use the vulnerability to try to collect the memory leaks. This may contain sensitive data from any other co-hosted websites. Shared hosting is commonly used by many site owners with limited requirements; OptionsBleed puts those users at risk.
Both the 2.2.x (up to 2.2.34) and the 2.4.x branches (up to 2.4.27) are affected by this vulnerability. Patches have already been released by many Linux distributions to cover this flaw, and we recommend that system administrators do so if they haven’t already.
Conclusion
Deep Security customers can use the following DPI rule to configure allowed HTTP methods in their environment and restrict the possibility of data leak through requests with unknown HTTP methods. A separate rule specifically focused on this vulnerability has been released as well.
System administrators should upgrade their installed versions of Apache HTTP Servers and disable the use of .htaccess files, if possible. Site owners without access to these directly and reliant on their ISPs should prod these service providers to upgrade as well.
TippingPoint has posted a Customer Shield Writer (CSW) file for this vulnerability that are available for customers to download on TMC. The applicable rule is as follows:
- C1000002: HTTP: Apache Server Options Information Disclosure Vulnerability