This is one for the pen-testers. We all know it’s fairly simple to fingerprint a webserver and fingerprinting a web application firewall like ModSecurity is probably even easier. It takes a bit of knowledge though and if you want to drill down on the ruleset, you should now the ruleset a bit.
So here is a benchmark for the OWASP ModSecurity Core Rules: A parameter with a value of /etc/passwd will violate exactly one rule:
* 950005: Remote File Access Attempt (Core Rules 2.2.X)
* 930120: OS File Access Attempt (Core Rules 3.0.0-dev)
In anomaly scoring mode (which is what most people run), this will give you a score of 5. Now here is the thing: A 2nd parameter with the same value, will score another 5 points, summing 10. And so forth. You can use this to determine the anomaly threshold on a server. It’s a bit boring to do this by hand, so here is a script:
$> determine-crs-limit.sh https://www.example.com/cms/index Calling URL with request resulting in score 5 : passed Calling URL with request resulting in score 10 : passed Calling URL with request resulting in score 15 : passed Calling URL with request resulting in score 20 : blocked The ModSecurity Core Rules Anomaly Limit is between 16 and 20.
Now this does not prove that this is a ModSecurity site or that the Core Rules are really in place. But changing the response depending on the number of faulty parameters sent is a strong indicator of you facing a CRS site in blocking mode.
Here is the script determine-crs-limit.sh:
#!/bin/bash # # Determine the ModSec anomaly score limit of a site # # Copyright (C) 2016 Christian Folini: folini@netnea.com # # TODO: # - We raise the score in steps of 5. # We will not hit the exact limit that way. # It is thus possible that the actual limit is a 1, 2, 3 or 4 # points below our report. But never 5 point below. # - Make the limit an optional parameter # URL="$1" TESTLIMIT=100 if [ -z "$URL" ]; then echo "URL parameter not passed. This is fatal. Aborting." echo "Usage: $0 https://www.example.com/index.html" exit 1 fi echo "$URL" | egrep -v -q "^http" if [ $? -eq 0 ]; then echo "URL parameter does not start with http/https. This is fatal. Aborting." echo "Usage: $0 https://www.example.com/index.html" exit 1 fi I=5 PARAMETER="" while [ $I -le $TESTLIMIT ]; do if [ ! -z "$PARAMETER" ]; then PARAMETER="$PARAMETER&" fi PARAMETER="${PARAMETER}a$I=/etc/passwd" MYURL="$URL?$PARAMETER" echo -n "Calling URL with request resulting in score $I : " STATUS=$(curl -k -o /dev/null -s -w "%{http_code}\n" "$MYURL") if [ "$STATUS" == "000" ]; then echo "failed" echo echo "Curl call failed for unknown reasons. This is fatal. Aborting." exit 1 elif [ "$STATUS" == "301" -o "$STATUS" == "302" -o "$STATUS" == "307" ]; then echo "redirected" echo echo "Redirection is bad as it is possible ModSecurity rules were shortcut." echo "Use an URL that results in a http status code 200." echo "This is fatal. Aborting." exit 1 elif [ "$STATUS" == "403" ]; then echo "blocked" if [ $I -eq 5 ]; then echo echo "The ModSecurity Core Rules Anomaly Limit is either between $((I-4)) and $I or" echo "there is no anomaly scoring and the rule hit blocks immediately." echo else echo echo "The ModSecurity Core Rules Anomaly Limit is between $((I-4)) and $I." echo fi exit 0 else echo "passed" fi I=$((I+5)) done echo echo "The limit is higher than $((I-5)), or there are no ModSecurity Core Rules at all."
This is obviously a script with a very limited functionality. But it’s a start. If I see the need, I might kick the can a bit further down the street.
Usage of the program presented above for fingerprinting targets without prior mutual consent is probably illegal in your legislation. It is the end user’s responsibility to obey all applicable local, state and federal laws. The author or netnea assume no liability and are not responsible for any misuse or damage caused by this program.
Christian Folini Follow @ChrFolini Tweet