Mod_security: How to log POST requests for specific URI

apache-2.4loggingmod-security

I'm trying to set up mod_security to log POST requests payload for a specific URI, as it seems that a customers webpage is used as a spam relay and these requests corrupt the server side cache.

I started by following this blog post but it seems rather old and outdated. It's not working with our environment which is Apache 2.4 and mod_security 2.8. So I enhanced that config by this serverfault answer.

Inside the relevant vhost config mod_security is configured like this:

<IfModule security2_module>
    SecRuleEngine On
    SecAuditEngine RelevantOnly
    SecAuditLog logs/audit.log
    SecRequestBodyAccess On
    SecAuditLogParts ABCFHJKZ

    SecDefaultAction "phase:2,nolog,noauditlog,pass"

    SecRule REQUEST_METHOD "^POST$" "id:'1234',phase:2,chain,allow,ctl:auditEngine=On"
    SecRule REQUEST_URI "^\/en\/us\/$"
</IfModule> 

The result is that every POST request is logged into audit log. But only the POST request to the homepage https://<SITE>/en/us/ should be logged. In my understanding this should be done by chaining to the second SecRule which matches the request URI against the given regex. I also tried different versions of the regex without success.

Best Answer

It's a little confusing but some of the actions specified in the first rule will run for each rule matched in the chain and some only if all rules match (the author of ModSecurity has stated in hindsight it would have been better to put the rules on the last chained rule rather than the first). See here for more details: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#chain:

Special rules control the usage of actions in chained rules:

  • Any actions that affect the rule flow (i.e., the disruptive actions, skip and skipAfter) can be used only in the chain starter. They will be executed only if the entire chain matches.
  • Non-disruptive rules can be used in any rule; they will be executed if the rule that contains them matches and not only when the entire chain matches.
  • The metadata actions (e.g., id, rev, msg) can be used only in the chain starter.

So rule should be this so logging is only turned on when first and second rule matches:

SecRule REQUEST_METHOD "^POST$" "id:'1234',phase:2,chain,allow"
SecRule REQUEST_URI "^\/en\/us\/$" "ctl:auditEngine=On"

Note also this will allow the rule and skip all future rules. You might be better to pass the rule instead. That way it will definitely be logged but still run other rules. However if this is your only rule as per the config you've shown it won't really matter, but still good practice.

Related Topic