Headline
CVE-2021-42717: ModSecurity DoS Vulnerability in JSON Parsing (CVE-2021-42717)
ModSecurity 3.x through 3.0.5 mishandles excessively nested JSON objects. Crafted JSON objects with nesting tens-of-thousands deep could result in the web server being unable to service legitimate requests. Even a moderately large (e.g., 300KB) HTTP request can occupy one of the limited NGINX worker processes for minutes and consume almost all of the available CPU on the machine. Modsecurity 2 is similarly vulnerable: the affected versions include 2.8.0 through 2.9.4.
ModSecurity is an open-source WAF engine maintained by Trustwave. This blog post discusses an issue with JSON parsing that could enable a Denial of Service (DoS) attack by a malicious actor. The issue has been addressed with fixes in both v2 and v3.
ModSecurity includes a JSON parser to allow for parsing of HTTP request bodies that are in the JSON format. Most commonly, the parser is activated when the HTTP Content-Type request header is of type 'application/json’. However, the JSON parser can optionally be engaged for other Content-Type values as well.
ModSecurity is distributed with a file called 'modsecurity.conf-recommended’. It includes a small number of configuration directives and rules that are typically desirable. This configuration file includes rule 200001 which enables the JSON request body processor, and this rule is enabled by default. The vulnerability described herein is not dependent on any other ruleset being installed. For a particular installation of ModSecurity, unless either (1) any rules that activate the JSON parser have been removed or commented out, or (2) ModSecurity was built without the JSON parser code (yajl), then it is likely vulnerable.
Vulnerability Details
The ModSecurity team recently received a responsible disclosure from Andrea “theMiddle” Menin about a use case that could facilitate a DoS attack. Thank you to the researcher for discovering and responsibly disclosing the issue, as well as for assisting with the verification of the eventual fix. Thanks also to Ervin Hegedüs for confirming the issue in v2 and for assisting with validating the fix in that branch.
Valid JSON can include nesting. As an example, the following is valid JSON with a maximum depth of three:
{"key1":{"key1_1":{"key1_1_1":99}}}
The use case of concern here is when the greatest depth in the JSON request body is very large. Once the depth is in the many tens of thousands, resource consumption escalates considerably and ModSecurity may delay a request for an excessive period while performing the JSON parsing. If a large enough number of such malicious requests are running simultaneously, this could render the webserver unable to respond to legitimate requests in a timely manner.
The negative performance impact on ModSecurity continues to increase as the parsing depth grows larger. Since increasing the JSON parsing depth requires adding additional characters ( e.g. ‘{’ ), this means an attacker who wants to increase the parsing depth must also make the overall request body larger. This has implications for the non-upgrade mitigation strategies suggested in the final section of this document.
The ModSecurity Fixes: v2.9.5, v3.0.6
ModSecurity v2.9.5 and v3.0.6 address this issue with a configurable limit on the maximum depth that will be accepted during JSON parsing. If that maximum is exceeded, the JSON parsing will halt immediately, while setting ModSecurity’s standard REQBODY_ERROR. There is a default depth limit of 10,000, but this can be customized – either higher or lower – with a new Configuration item: SecRequestBodyJsonDepthLimit. It is expected that most installations should find the default value to be sufficient.
Releases for v3.0.6 for Nginx and v2.9.5 for Apache are available immediately, v2.9.5 for IIS will be available in the next few days. Users of ModSecurity that can’t update immediately may wish to consult the following section covering other mitigation strategies.
Other Ways to Mitigate the JSON Parsing Depth Issue
Upgrading to an updated version of the software is advisable, but that may not be possible for all users in the short term. While there is no universally suitable substitute to upgrading, some installations may be able to mitigate this issue with a rule update. Some example scenarios:
1) None of my web applications accept JSON request bodies
Possible Mitigation: Disable any ModSecurity rules that activate the JSON parser.
2) Some of my web applications accept JSON request bodies but they are all small
Possible Mitigation: Create a phase:1 chained rule that will reject requests that would use the JSON parser if the Content-Length exceeds a certain size (10,000 to 20,000 bytes is likely safe in most installations). Some v2 users may alternatively be able to make use of the SecRequestBodyNoFilesLimit configuration item if other non-file request bodies are likewise expected to be below similar thresholds. Special note to users with ModSecurity <v2.9.3: although the problem exists in earlier versions like v2.9.2, it appears to require a larger request body size to trigger problematic delays, which means that limits involving the request body size can probably be larger (perhaps 40,000 to 50,000 bytes) and still provide decent protection in most installations.
3) A few of my web applications expect larger JSON request bodies
Possible Mitigation: Consider creating a rule as in (2) above but do not have it run for the cases where such larger request bodies are expected. Limiting the application could be done either with an additional rule in the chain, or by removing the rule at runtime (e.g. ctl:ruleRemoveById) when relevant conditions have been met. This approach does not provide robust protection, but it may provide reasonable protection against less-motivated attackers.