Recent Posts


« | Main | »

Apache mod_security testing examples

By Dale Reagan | November 8, 2010

Testing mod_security rules can be tricky, i.e. things work well in ‘testing’ but you encounter a ‘whoops’ in production.  Hmm.  Figuring out what is different can be a bear.  Note that this discussion presumes that you already have mod_security installed and working…

Scenario one – including a special test configuration

</Location /some_web_folder/> ## used for testing.
    Include /path_to_testrules/test-rules.conf

Ok, you limit the impact of your new, test rules to a specific path for your test domain or test server.  Things work as expected during testing. You implement the new rule(s) on your production web and you are immediately blocked, OR all access is blocked.  Hmmm. Time for the UN-Do button…  I will return to this later – I’ll try something simpler first.

I was getting occasional SPAM messages from an ancient feedback form; since the web site was intended for a narrow audience (i.e. US visitors) it was easy/simple to create a rule to stop the spammers (all from foreign countries…)  Also note that other means of communication were presented on the site so limiting access to the feedback script would simply present an inconvenience to the foreign visitor with a real interest in communicating with the web site  owner…

## mod_security rule set to limit specific CGI-Bin access by country
##create a 'splash' page and rule that always allows access
SecRule REQUEST_URI "/splash/" phase:1,allow,nolog,noauditlog,ctl:ruleEngine=Off

Scenario two – testing a specific URI

## rule set (chained rules) to limit specific CGI-Bin access by country
SecRule REQUEST_URI /cgi-bin/ "phase:1,log,status:403,redirect:/splash/,chain,msg:'SomeScript-Request_Denied'"
SecRule REMOTE_ADDR "@geoLookup" "chain"
SecRule GEO:COUNTRY_CODE "!@streq US"  "t:none"
  1. specify: URL to match for the rule set, redirect to /splash/ if there is a match; following two rules must match, log a custom message
  2. extract the GeoIP information
  3. check the GeoIP information (Country code) for a match; i.e. “!@streq US” = “there is a match if the string does NOT equal ‘US’
  4. if the country code is ‘US’ then access is allowed; if not then the visitor is re-directed to the /splash/ page (which, of course, needs to exist and the page should provide some helpful information for humans…)

Using ‘containers’ for testing with a more refined mod_security configuration

<Location /cgi-bin/>  # specify a container - can a sub-folder in your web
# create a custom log as well as a custom log level for the container
SecDebugLog /path_to_mod_security_logs/container_test.log
SecDebugLogLevel 3
## rule set to limit specific CGI-Bin access by country - same rule as above

SecRule REQUEST_URI /cgi-bin/ “phase:1,log,status:403,redirect:/splash/,chain,msg:’SomeScript-Request_Denied'”
SecRule REMOTE_ADDR “@geoLookup” “chain
SecRule GEO:COUNTRY_CODE “!@streq US”  “t:none
</Location> # ‘close’ the container

Test, test, TEST!  Adding a container specific log file as well as adjusting the debug level should provide a good starting point for testing and reviewing your proposed mod_security changes.   When placing ‘tested’ rules into a production setup I suggest using a custom log as well (until you confirm that all is well with the new rule.)   Rules in containers are isolated – they will not be called unless the container is accessed.   Likewise, any ripples from your new rules (interactions with the main rule set) will not occur until you install the rule outside of a container (conflicts do occur.)

Returning to the initial example:

</Location /some_web_folder/> ## used for testing.
    Include /path_to_testrules/test-rules.conf

In the case above the ‘test-rules.conf’ rules worked fine inside of the container but un-expected/un-wanted results occurred outside  of this isolation.  The issue was resolved after detailed logging was reviewed – there was a variable conflict – there was non-unique variable in the new test rules and other rules (in the production set) were ‘catching’ it and denying access, ummm – globally.  TEST! Test! TesT!  🙂

Ok – how might you use detailed logs after installing rules ‘normally‘, i.e. the new rules are evaluated during the global rule-evaluation-process but you do not want detailed logging from ‘normal visitors’?   Simple – Create a custom container just for logging!  Since you are the only one accessing/using the URI you will limit logging (esp. if you use a custom, non-advertised/listed Alias with perhaps access limitations set to your IP address…)

</Location /some_web_folder/> ## used for testing.
# create a custom log as well as a custom log level for the container
SecDebugLog /path_to_mod_security_logs/container_test.log
SecDebugLogLevel 3

And of course, TEST! Test! TesT!  🙂

A more specific example – limiting login access in WordPress.

Provided that you install WordPress as your default container for your domain under Apache, then this rule will:

<Location /wordpress/wp-login.php>
SecRule REQUEST_URI /wordpress/wp-login.php “phase:1,log,status:403,redirect:/splash/,chain,msg:’WP-Login-Request_Denied'”
SecRule REMOTE_ADDR “@geoLookup” “chain
SecRule GEO:COUNTRY_CODE “@pm US CN GB”  “t:none ## only allow access from the US, CN or GB

#SecRule GEO:COUNTRY_CODE “!@streq CN”  “t:none ## only allow access from China


Note that the only changes from the previous example are the URI and allowing access from more than one country…  Want to limit comment posting by country?  Just change the URI to /wordpress/wp-comments-post.php and, of course, TEST.

While these examples use mod_security it is also possible to limit access by using mod_geoip alone.  In many cases mod_geoip is a simpler approach for managing URL-specific access while mod_security provides additional levels of control, i.e. you add additional, chained rules to create a granular level of access instead of an all or none control.  Of course, using GeoIP variables in your web site code is also possible and might be a better approach for very specific needs.

Using some tools (like mod_geoip, mod_security) effectively can be quite tricky so contact me if you need another set of eyes/hands to resolve any issues – I am available for short or long term projects where you might need assistance with your Linux/Apache systems. I may be able to save you hours/days in resolving issues or implementing new solutions.   🙂

Topics: Computer Technology, System and Network Security, Unix-Linux-Os, Web Technologies | Comments Off on Apache mod_security testing examples

Comments are closed.

YOUR GeoIP Data | Ip:
Continent: NA | Country Code: US | Country Name: United States
Region: | State/Region Name: | City:
(US only) Area Code: 0 | Postal code/Zip:
Latitude: 38.000000 | Longitude: -97.000000
Note - if using a mobile device your physical location may NOT be accurate...

Georgia-USA.Com - Web Hosting for Business