ModSecurity Mitigations for ASP.NET HashTable DoS Vulnerability (CVE-2011-3414)

ThreatPost had a news story today about PoC code that was released to the full disclosures mail-list:

ASP.NET HashDoS PoC/exploit payload

From: Disaster <disaster () sdf-eu org>
Date: Fri, 6 Jan 2012 23:19:07 +0000


ASP.NET HashDoS PoC/exploit payload ready for download.
get it. use it. spread it.

use it your own way.

curl | curl http://target/website.aspx -d () -
cat asphashdos.1mb | curl http://target/website.aspx -d () - 

We are Legion. Expect us.

The PoC code comes in two different sizes: a 1 MB file and a 4 MB file. The HTTP payload consists of a very large number of random parameter names, all with empty payloads. Here is a short snippet:


The result of this is that the empty payloads will all be hashes by ASP.NET to the same value, thus causing the collision DoS scenario.

ModSecurity Mitigations

Restrict the Request Body Size

ModSecurity includes a directive called SecRequestBodyNoFilesLimit that can restrict the request body size as follows:


Description: Configures the maximum request body size ModSecurity will accept for buffering, excluding the size of any files being transported in the request. This directive is useful to reduce susceptibility to DoS attacks when someone is sending request bodies of very large sizes. Web applications that require file uploads must configure SecRequestBodyLimit to a high value, but because large files are streamed to disk, file uploads will not increase memory consumption. However, it's still possible for someone to take advantage of a large request body limit and send non-upload requests with large body sizes. This directive eliminates that loophole.

Syntax:SecRequestBodyNoFilesLimit NUMBER_IN_BYTES

Example Usage:SecRequestBodyLimit 131072

Scope: Any

Version: 2.5.0

Default: 1048576 (1 MB)

Generally speaking, the default value is not small enough. For most applications, you should be able to reduce it down to 128 KB or lower. Anything over the limit will be rejected with status code 413 (Request Entity Too Large). There is a hard limit of 1 GB.

The ModSecurity source code includes a modsecurity.conf-recommended file with the following setting:

# Maximum request body size we will accept for buffering. If you support
# file uploads then the value given on the first line has to be as large
# as the largest file you are willing to accept. The second value refers
# to the size of data, with files excluded. You want to keep that value as
# low as practical.
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072

When the Hash DoS PoC is run against an Apache server with this ModSecurity setting, it will generate the following alert:

[Mon Jan 09 16:42:05 2012] [error] [client] ModSecurity: Request body no files data length is larger than the configured limit (131072).. Deny with code (413) [hostname "localhost"] [uri "/website.aspx"] [unique_id "TwtfLcCoqAEAAACKG2YAAAAB"]

Restrict the Number of ARGS

In order to carry out a successful Hash DoS attack, the payload needs to have an abnormally large number of parameters. For example, the 1 MB DoS file has 10749 parameters in it. The OWASP ModSecurity Core Rule Set (CRS) has a default rule in the modsecurity_crs_23_request_limits.conf file that will restict the total number of ARGS within a request:

# Maximum number of arguments in request limited
SecRule &TX:MAX_NUM_ARGS "@eq 1" "chain,phase:2,t:none,block,msg:'Too many arguments in request',id:'960335',severity:'4',rev:'2.2.3'"
	SecRule &ARGS "@gt %{tx.max_num_args}" "t:none,setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},setvar:tx.policy_score=+%{tx.notice_anomaly_score},setvar:tx.%{}-POLICY/SIZE_LIMIT-%{matched_var_name}=%{matched_var}"

The amount of ARGS allowed is controlled by the Admin and set within the modsecurity_crs_10_config.conf file:

# -=[ HTTP Policy Settings ]=-
# Set the following policy settings here and they will be propagated to the 23 rules
# file (modsecurity_common_23_request_limits.conf) by using macro expansion.  
# If you run into false positives, you can adjust the settings here.
# Only the max number of args is uncommented by default as there are a high rate
# of false positives.  Uncomment the items you wish to set.
## Maximum number of arguments in request limited
SecAction "phase:1,id:'981211',t:none,nolog,pass,setvar:tx.max_num_args=255"

When the Hash DoS PoC code is run against an Apache server with the CRS configured in a blocking mode, it will deny the request and trigger the following alert:

[Mon Jan 09 16:50:51 2012] [error] [client] 
ModSecurity: Access denied with code 403 (phase 2). Operator GT matched 255 at ARGS. [file "/usr/local/apache/conf/crs/base_rules/modsecurity_crs_23_request_limits.conf"] [line "31"] [id "960335"] [rev "2.2.3"] [msg "Too many arguments in request"] [severity "WARNING"] [hostname "localhost"] [uri "/website.aspx"] [unique_id "TwthOsCoqAEAAAYxEskAAAAA"]

Identifying Repetitive Payloads

As stated above, this attack works by forcing a large number of hash collisions by setting a large number of payloads all with the same value. In the PoC shown, all the parameter payloads are empty and thus would result in the same hash value. The payload doesn't have to be empty. It could be a 1 or the word foo, etc... but they all have to be the same. Due to this exploit characteristic, we can constuct the following ModSecurity rule that will identify repetitive payloads:

SecRule &ARGS "@ge 1000" "chain,phase:2,t:none,block,msg:'Possible Hash DoS Attack Identified.',tag:''"
        SecRule REQUEST_BODY "^\w*?=(.*?)&\w*?=(.*?)&\w*?=(.*?)&\w*?=(.*?)&" "chain,capture"
                SecRule TX:1 "@streq %{tx.2}" "chain,setvar:tx.hash_dos_match=+1"
                        SecRule TX:2 "@streq %{tx.3}" "chain,setvar:tx.hash_dos_match=+1"
                                SecRule TX:3 "@streq %{tx.4}" "chain,setvar:tx.hash_dos_match=+1"
                                        SecRule TX:HASH_DOS_MATCH "@eq 3"

This rule first checks to see if the number of ARGS is more than 1000. If this is true, then we use a regex check to capture the first four parameter payloads. These are saved within the ModSecurity TX:1, TX:2, etc... transactional variables. We then check these variables against each other to see if they are the same. If they are, then we increment a new "tx.hash_dos_match" variable. The final rule checks the variable value if it is 3, then we trigger an alert as this means all 4 values we the same. If we run the Hash DoS PoC against a ModSecurity host with this ruleset, we get this alert:

[Mon Jan 09 16:56:15 2012] [error] [client] ModSecurity: Access denied with code 403 (phase 2). Operator EQ matched 3 at TX:hash_dos_match. [file "/usr/local/apache/conf/crs/base_rules/modsecurity_crs_15_custom.conf"] [line "1"] 
[msg "Possible Hash DoS Attack Identified."] [tag ""] [hostname "localhost"] [uri "/website.aspx"] [unique_id "Twtif8CoqAEAAApLJl8AAAAA"]

Check ARGS Names against PoC Data

The final mitigation option is the weakest of the rules from a potential false negative perspective but it will identify is some is running this PoC against your site. The goal of this rule is to check the ARGS_NAMES in the current transaction against a list of the parameter names from the PoC file. Here is the new rule to use:

SecRule ARGS_NAMES "@pmFromFile hash_dos_param_names.txt" "phase:2,t:none,block,msg:'Hash DoS PoC Attack Identified.',tag:''"

This rule uses the @pmFromFile fast set-based pattern matching operator to check data in the hash_dos_param_name.txt file.

When we run the PoC against a ModSecurity host with this rule, we get the following alert:

[Mon Jan 09 17:05:59 2012] [error] [client] ModSecurity: Access denied with code 403 (phase 2). Matched phrase "3QBZJK5ZX" at ARGS_NAMES:3QBZJK5ZX. [file "/usr/local/apache/conf/crs/base_rules/modsecurity_crs_15_custom.conf"] [line "8"] 
[msg "Hash DoS PoC Attack Identified."] [tag ""] [hostname "localhost"] [uri "/website.aspx"] [unique_id "Twtkx8CoqAEAABFCGP0AAAAD"]

Trustwave reserves the right to review all comments in the discussion below. Please note that for security and other reasons, we may not approve comments containing links.