Fix ModSecurity false positives on __cf_bm CloudFlare cookie

OVERVIEW

If your web site uses both ModSecurity and CloudFlare, and visitors to your web site are blocked intermittently, then the problem could be a Cross-Site Scripting (XSS) protection rule in ModSecurity. This article will show you how to fix the problem.

BACKGROUND

Recently, CloudFlare started injecting a cookie into all requests with a name of __cf_bm. The cookie contains a timestamp and some hashed and encoded data, and is used by CloudFlare for bot management.

The OWASP/Modsecurity rule set contains a rule #941120, which tries to stop XSS attacks that attempt to exploit event handlers, such as onload or onerror. But, the history of issues with rule 941120 shows that this rule might cast too wide a net when it comes to examining cookie contents. So the problem is with rule 941120, and not anything CloudFlare is doing wrong.


HOW TO DETECT THE PROBLEM

Assuming that you can view ModSecurity log files, you could search through the modsec_audit.log file with a command similar to this…

grep -F REQUEST_COOKIES:__cf_bm /var/log/apache2/modsec_audit.log

If rule 941120 triggered recently, then should see something similar to the following…

The three highlighted sections show us the location of the file containing the rule, the rule number, and the matching data that triggered the rule. The file containing the triggered rule is /usr/share/modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf. The rule ID is 941120. And the matching data was found within REQUEST_COOKIES:__cf_bm.

Now, if we search REQUEST-941-APPLICATION-ATTACK-XSS.conf for 941120 near line 110, we find the following…

Without digging too deep into the syntax of ModSecurity rules, the highlighted section of the rule gives us a clue on how to fix the problem. REQUEST_COOKIES means to apply the rule to cookies sent by the visitor in the web server request. The | symbol means apply this rule to each target specified; a logical “Or.” !REQUEST_COOKIES:/__utm/ means to not (the ! symbol negates what follows) examine cookies that match the regular expression /__utm/. Cookies named __utm are tracking cookies from Google’s Urchin Tracking Module.

What this tells us, is that this rule already had a problem with false positives on Google tracking cookies. Since Google tracking cookies are everywhere, the developers had a choice; either make an exception for Google tracking cookies, or risk widespread disabling of this rule. Obviously, they chose to make an exception for Google.

This gives us a clue how to make an exception for CloudFlare’s __cf_bm cookie. We can use ModSecurity’s SecRuleUpdateTargetById directive. This directive allows us to append more items to a rule’s target list. It is preferable to use SecRuleUpdateTargetById instead of editing the original rule because we don’t want updates to the OWASP/Modsecurity rule files to overwrite our fix.

HOW TO FIX RULE 941120

The following directive should prevent the contents of the __cf_bm from triggering rule 941120…

# Don't allow rule 941120 to block requests due to CloudFlare __cf_bm cookie content.
SecRuleUpdateTargetById 941120 "!REQUEST_COOKIES:/__cf_bm/"

You can append this to /etc/modsecurity/crs/crs-setup.conf. If you don’t have access to this file, and use the Apache web server, it might also work if you place it in the .htaccess file in the root directory for your web site. You could also place it in a .conf file in /etc/apache2/conf-available and enable that configuration file with the a2enconf command.

CONCLUSION

The expression on[a-zA-Z]+ in this rule does match things like onLoad and onError. But it also can cause false positives by matching any text that contains on followed by one or more letters. There is a pretty good likelihood for this to happen in legitimate cookie content.

A fix for rule 941120 that looks promising is coming out in version 4.0 of the ModSecurity core rule set. Once version is available for your distribution, remove the SecRuleUpdateTargetById rule shown above from your system. Leaving this hack in place just creates a hole in the rule for hackers to exploit.