Writing your own ModSecurity rules

Published: 2015-07-29

ModSecurity is a module, which is available for Webservers, it implements a Web application firewall, in short a “WAF”.

Web application firewalls help network administrators to secure the calls that are being made to websites, i.e. to avoid all the common attacks like XSS or SQL injection attacks.

Most of those solutions cost alot of money, thus they re unfeasible for personal usage, ModSecurity is the only WAF that I am aware of which you can download and use for free.

I am not going into howto install it and configure it, as there are many very good tutorials on the web, which already feature that base process.

ModSecurity is using so called “rule files” that are being checked when the website is being browsed to, the base rule files already contain very good rules to secure common web applications and websites, but they are by no means all that usable out of the box.

Most other tutorials tell you that you should disable rules if they interfere with your website, I don't like that solution, as it opens up possible security holes.

To start up, we create a new rule file within the /usr/share/modsecurity-crs directory, open it with our favorite text editor, I am a big fan of vim, as nowadays thats available on most servers by default.

I am calling my file modsecurity crs 48 local exceptions.conf

--4d5aa166-F-- HTTP/1.1 403 Forbidden Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 185 Keep-Alive: timeout=5, max=99 Connection: Keep-Alive Content-Type: text/html; charset=iso-8859-1 --4d5aa166-E-- --4d5aa166-H-- Message: Access denied with code 403 (phase 2). Pattern match "(?i:(\\!\\=|\\&\\&|\\|\\||>>|<<|>=|<=|<>|<=>|xor|rlike|regexp|isnull)|(?:not\\s+between\\s+ 0\\s+and)|(?:is\\s+null)|(like\\s+null)|(?:(?:^|\\W)in[+\\s]*\\([\\s\\d\"]+[^()]*\\))|(?:xor|<>|rlike(?:\\s+binary)?)|(?:regexp\\s+binary))" at REQUEST_COOKIES:nf_wp_session. [file "/usr/share/modsecurity-crs/activated_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "70"] [id "981319"] [rev "2.2.5"] [msg "SQL Injection Attack: SQL Operator Detected"] [data "||"] [severity "CRITICAL"] [tag "WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"] Action: Intercepted (phase 2) Stopwatch: 1438210301649575 10937 (- - -) Stopwatch2: 1438210301649575 10937; combined=4923, p1=738, p2=3477, p3=0, p4=0, p5=404, sr=251, sw=304, l=0, gc=0 Response-Body-Transformed: Dechunked Producer: ModSecurity for Apache/2.9.0 (http://www.modsecurity.org/); OWASP_CRS/2.2.5. Server: Apache WebApp-Info: "default" "fe01c8e72dddd18e62095123af081877%7C%7C1438244930%7C%7C1438243130" "" Engine-Mode: "ENABLED" --4d5aa166-Z--

now we check the mod security audit log for entries, to tell us which rules interfer with our website, a typical entry in that log file looks like this:

SecRule REQUEST_COOKIES|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "(?i:(\!\=|\&\&|\|\||>>|<<|>=|<=|<>|<=>|xor|rlike|regexp|isnull)|(?:not\s+between\s+0\s+and)|(?:is\s+null)|(like\s+null)|(?:(?:^|\W)in[+\s]*\([\s\d\"]+[^()]*\))|(?:xor|<>|rlike(?:\s+binary)?)|(?:regexp\s+binary))" "phase:2,rev:'2.2.5',capture,t:none,t:urlDecodeUni,block,msg:'SQL Injection Attack: SQL Operator Detected',id:'981319',logdata:'%{TX.0}',severity:'2',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',setvar:'tx.msg=%{rule.msg}',setvar:tx.sql_injection_score=+%{tx.notice_anomaly_score},setvar:tx.anomaly_score=+%{tx.notice_anomaly_score},setvar:tx.%{rule.id}-WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}"

now we check the mod security audit log for entries, to tell us which rules interfere with our website, a typical entry in that log file looks like this:

Now this tells us alot of stuff, first of all, we see that access to our website was denied (http error 403), modsecurity thinks it was an SQL injection attack. The rule that was causing this has the id 981319 and is on line 70 of the file modsecurity crs 41 sql injection_attacks.conf

now we have a look at that file:

modsecurity offers a few ways to disable this rule in certain cases using regular expressions, a full listing of all modsecurity variables may be found in theirs reference manual

let's say we want to update that rule to exclude REQUEST COOKIES:nf wp_session…

we add the following to our modsecurity crs 48 local exceptions.conf file:

And restart our Webserver. And that one error will be gone.

I hope you found my short tutorial useful, as usual, if you got any questions or got a better idea to do things, please let me know below.