Disable ModSec2 per domain per folder – modsec rules explained

When a client complaints for a modsec error, it is not advisable to turn off a specific rule he has issue with globally. Nor it is not advisable to turn off the modsec completely for that domain. Prior to modsec2, we were able to turn off the modsec completely and per rulewise through .htaccess of a domain. From modsec2 onwards, it is not possible to use .htaccess to disable modsec. We need to add rules inside the file “/usr/local/apache/conf/whitelist.conf” or disable using the modsec rule id.
 
We can disable modsec for a domain completely using the following rule added to the whitelist.conf.
 
SecRule SERVER_NAME “domain.com” phase:1,nolog,allow,ctl:ruleEngine=off
 
So what does these words specify? Some are pretty straight forward:
 
nolog:Prevents rule matches from appearing in both the error and audit logs.
allow: Stops rule processing on a successful match and allows the transaction to proceed.
ctl: The ctl action allows configuration options to be updated for the transaction. This means what action should be taken to the configuration options. For eg, ruleEngine is “on” by default. We are telling modsec to turn it “off”, when the server name matches domain.com. So this means the action to be taken.
 
Now what is the stuff called phase:1 ?
ModSecurity 2.x allows rules to be placed in one of the following five phases:
Refer for more details here
 
I will explain phase:1 now.
Phase 1
Phase Request Headers
Rules in this phase are processed immediately after Apache completes reading the request headers (post-read-request phase). At this point the request body has not been read yet, meaning not all request arguments are available. Rules should be placed in this phase if you need to have them run early (before Apache does something with the request), to do something before the request body has been read, determine whether or not the request body should be buffered, or decide how you want the request body to be processed (e.g. whether to parse it as XML or not).
 
Modsec applies the rules specified as phase:1 at the first time the apache request is received. Not much would have been done to the request. this time. I will explain with an example now.
 
Lets come back to the initial situation. We had disabled modsec for a domain completely. But this is not a good practice. It is recommended to disable modsec per domain, per location and per rule wise. Don’t you think it is ideal case? How do we do it in modsec2?
 
In modsec2, we can see there comes a lot of default rules. If you see such a rule, you will notice there is an id attached to the rules. See below.
 
—-
#Generic PHP exploit signatures
SecRule REQUEST_URI “(chr|fwrite|fopen|system|e?chr|passthru|popen|proc_open|shell_exec|exec|proc_nice|
proc_terminate|proc_get_status|proc_close|pfsockopen|leak|apache_child_terminate|posix_kill|posix_mkfifo|posix_setpgid|
posix_setsid|posix_setuid)\(.*\)\;” “id:330001,rev:1,severity:2,msg:’Generic PHP exploit pattern denied'”
 
We can disable the above modsec rule for a domain using the id by adding the following line inside the file /usr/local/apache/conf/whitelist.conf
 
SecRule SERVER_NAME “domain.net” phase:1,nolog,allow,ctl:ruleRemoveById=330001
 
But what we need not disabling fully a rule per domain. But disable per folder or location. How to do this?
 
In Modsec, there is an option called SecRuleRemoveById. We can use this inside the httpd.conf,  virtualhost entry of the domain for which we need to disable a specific modsec rule on a specific folder. If we need to disable the above rule id for the location domain.com/help  ie /home/username/public_html/help, we can add these lines to the  virtualhost entry of the domain “domain.com”. This means domain.com/paypal will give modsec error while domain.com/help/paypal will not show error.
 
<LocationMatch “/help”>
SecRuleRemoveById 330001
</LocationMatch>
 
The above stuff is useful in cases like below. Here you can see the modsec causes when a page is loaded with an image named paypal.png inside the folder images. You can apply the above entry insdie the VH of domain.com for folder images.
 
—-
[Thu Jun 03 13:53:42 2010] [error] [client xx.xx.xx.xx] ModSecurity: Access denied with code 406 (phase 2). Pattern match “/paypal” at REQUEST_URI. [file “/usr/local/apache/conf/modsec2.global.conf”] [line “101”] [hostname “domain.com”] [uri “/image/paypal.png”] [unique_id “TAfsJkJH8oIAAFEcNNwAAAAA”]
—-
As the logs says, the rule responsible for this error is in the line 101 inside the file /usr/local/apache/conf/modsec2.global.conf. Lets see that.
 
SecRule REQUEST_URI “paypal” “deny,log,status:406”
 
Well did you get the “id” from the above rule? No right? The unique_id  seen in the log should not be confused with the “id”. unique_id is the unique id created by the modsec for a log message. So, without the id, we cannot disable the specific rule for a domain and location wise. How can we create an id for a specific rule? Modify the rule as follows inside the file /usr/local/apache/conf/modsec2.global.conf
 
SecRule REQUEST_URI “/paypal” “id:900000,deny,log,status:406”
 
Now we have created an ID for the specific rule. Now you can block this as explained above.
 
I will explain the phase:1 and phase:2 a bit more with an example. Imagine I am adding the phase:1 as follows to the above rule.
 
SecRule REQUEST_URI “/paypal” “phase:1,id:900000,deny,log,status:406”
 
This means when the request like domain.com/paypal reaches the apache, it ignores the request at the first stage of apache request processing. It will not even check if any <LocationMatch> is specified in the httpd.conf file.
 
If we change the rule as follows, ie add phase:2 instead of phase:1
 
SecRule REQUEST_URI “/paypal” “phase:2,id:900000,deny,log,status:406”
 
Here, the rule is applied to the request domain.com/paypal, during the later stage of apache request processing, ie not at the first stage. So the apache has got time and checks if there is any <LocationMatch> for the specific rule id. If it finds the below rule inside the httpd.conf file, the request is not checked again. ie it get whitelisted for the path /home/username/public_html/help.
 
<LocationMatch “/help”>
SecRuleRemoveById 900000
</LocationMatch>
 
 
Enjoy playing with the modsec rules. 🙂
Advertisements
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: