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:

bypan6 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/