ModSecurity 2 has been out for a while now, and although I have played with it some, I never found some time to upgrade my own servers. The upgrading generally went quite smooth, even though ModSecurity 2 changed quite a bit.
First of all there are now 5 phases where you can filter. Actually, one of them only applies to the logging, so you can filter in 4 phases. The phases are headers and body for both request and response traffic. Filtering on specific URIs can be done in phase 1 (request headers), while inspecting a POST payload requires phase 2 (request body).
Next, some shortcuts where removed. In 1.9.4 there was a variable called POST_PAYLOAD, that enabled the user to match against payloads from POST requests easily. Now there is REQUEST_BODY, but since that can be part of non-POST requests as well, you have to use:
SecRule REQUEST_METHOD “POST” chain
SecRule REQUEST_BODY “evil”
SecFilterSelective POST_PAYLOAD “evil”
One other change is visible above already. The keyword to create a rule has been changed from SecFilterSelective to SecRule. Many rules can be converted by just replacing the keyword, but certainly not all. A simple find/replace should not be done without a manual review!
I use a number of custom rules to protect certain parts of my server, so I needed to convert my rules. For most of them it was simply enough to replace SecFilterSelective with SecRule. For a few I had to replace the OUTPUT_STATUS variable with the RESPONSE_STATUS variable, as it is called now.
For one rule however, I had quite some problems to get it running correctly. This was the rule in 1.9.4 syntax:
# block wp-login.php
SecFilterSelective REMOTE_ADDR “!10.1.1.1” chain
SecFilterSelective REQUEST_URI “/wp-login.php”
This rule makes sure only 10.1.1.1 can open the login page, everyone else is redirected to a simple html page containing a ‘Access Denied – Logins disabled’ message. I converted it to the following:
SecRule REMOTE_ADDR “!10.1.1.1” chain
SecRule REQUEST_URI “/wp-login.php”
Guess what? It didn’t work. I’ve spend quite some time trying all kinds of variations of the rule, and finally I found out what the issue is. In 1.9.4 the rule actions, like deny, redirect etc could be in the final rule of a series of chained rules. With 2.0.4 this doesn’t work correctly. So when I changed the rules to the following, it worked:
# block wp-login.php
SecRule REMOTE_ADDR “!10.1.1.1” “chain,phase:1,log,deny,redirect:http://www.inliniac.net/nologin.html”
SecRule REQUEST_URI “/wp-login.php$”
I haven’t looked into this further to find out whether this is a bug or a feature.
The last thing that was interesting is the modsec2sguil script. There have been some changes to the alert files. So expect a new version of the script soon!