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.