07 July 2008

mod_security

mod_security is an open source Web application firewall which operates as an Apache module. mod_security inspects incoming requests (and, I believe, can also inspect outgoing responses) and take certain actions if a request (or response) matches a pattern. These actions can include logging and/or blocking the request. mod_security works sort of like anti-virus software, in that it comes with a ruleset which can identify common malicious activity (like cross-site scripting and SQL injection attempts). Like anti-virus software, it's necessary to update the ruleset from time to time.

I installed mod_security on a couple of production RHEL5 Web servers lately, and here are a few of my observations.

Installing mod_security is pretty easy and is documented in the mod_security download. I found that I needed to install the following packages to meet some dependencies and to build mod_security:
  • apr-devel
  • gcc-c++
  • httpd-devel
  • pcre and pcre-devel
  • libxml2-devel

I had the support of my managers to put mod_security in full blocking mode, so after copying the rules directory to /etc/httpd/modsecurity.d, I saved the following in /etc/httpd/conf.d/modsecurity.conf:

LoadFile /usr/lib/libxml2.so.2

LoadModule security2_module modules/mod_security2.so
LoadModule unique_id_module modules/mod_unique_id.so

<IfModule mod_security2.c>
Include modsecurity.d/*.conf
Include modsecurity.d/optional_rules/*.conf
</Ifmodule>


The Web servers run a variety of custom Web applications as well as some canned software like Webcalendar and Wordpress. I didn't experience any problems with the custom applications or Webcalendar, but mod_security took issue when someone tried to edit an existing blog post in Wordpress (curiously, there wasn't any trouble when submitting a new post). So I put the following in /etc/httpd/modsecurity.d/modsecurity_crs_15_customrules.conf:

<Directory /path/to/wordpress/wp-admin>
SecRuleEngine Off
</Directory>

I'm in the fortunate (and perhaps unusual) situation of being able to restrict access to the wp-admin directory by IP address, so I don't have the entire Internet hammering at the thing. Looks like blogsecurity.net has a custom mod_security configuration for Wordpress which I just haven't had time to try yet.

Another wrinkle I had was that some command-line Perl programs I run would be blocked because they weren't providing "accept" and "user-agent" request headers. One of these programs looked something like this:

#!/usr/bin/perl -w

use strict;
use HTTP::Request::Common;
use LWP::UserAgent;

my $ua = LWP::UserAgent->new();
my $uri = shift @ARGV;
my $res = $ua->request( GET $uri );
print $res->content();

I had to make the following two changes/addition:

$ua->agent('whinerack');
my $res = $ua->request( GET $uri, accept => 'text/html' );

(Looks like just about any non-blank user-agent will do.)

Another trick I've learned is that instead of using SecRuleEngine Off (like I did for the Wordpress wp-admin directory, which makes mod_security totally ignore that directory), you can use SecRuleEngine DetectionOnly, which makes mod_security log what it would do without actually blocking requests. This can be good for debugging.

And although I haven't needed it, the mod_security documentation suggests a way to whitelist requests from a specific host:

SecRule REMOTE_ADDR "^192\.168\.1\.100$" nolog,phase:1,allow


All in all, installing mod_security has been a fairly easy transition, and it's nice having another layer of protection.

8 comments:

BP said...

One useful thing you might want to know about the Wordpress specific rules in the link you posted..is that those rules were written for an earlier version of mod_security. If you're using mod_security2, those rules need to be translated because the syntax has changed.

mbrisby said...

Thanks for the tip, BP. I am using mod_security2, and I hadn't realized there was a compatibility issue.

In a recent wordpress upgrade (from v2.5 to v2.6, I believe), I ended up needing to disable mod_security for wp-login.php (like I did for the wp-admin directory). And it's probably better to do SecRuleEngine DetectionOnly, rather than SecRuleEngine Off (so that you can at least review the log entries).

And it looks like there's a new blogsecurity.net post talking about using mod_rewrite (I haven't had the chance to try this, either).

Anonymous said...

Thanks...helpful info.

Anonymous said...

hi
i want ignore all wp-admin folder in my sever
i have a 100 website that uses wordpress and i want ignore wp-admin for all .
how can i write a rule for this in modsecurity base_rule ?
tnx

mbrisby said...

@Anonymous, I'd probably try something like the following

<Directory ~ "/wp-admin">
SecRuleEngine Off
</Directory>

Or maybe DirectoryMatch

Anonymous said...

hey mbrisby
hi
i want write a rule like this rule :
SecRule ARGS /wp-admin phase:2,log,block,ctl:auditLogParts=+E
i want handle wp-admin request in modsecurity

Anonymous said...

where can i found all modsecurity v2 byteid ?

mbrisby said...

@Anonymous, I think wordpress and mod_security have a long history of not getting along, and I don't know a lot about getting them to work together. You might find some useful information at http://wpsecure.net/2012/01/using-mod_security-2-with-wordpress/