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:

  1. 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.

    ReplyDelete
  2. 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).

    ReplyDelete
  3. Anonymous12:38 AM

    Thanks...helpful info.

    ReplyDelete
  4. Anonymous7:18 AM

    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

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

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

    Or maybe DirectoryMatch

    ReplyDelete
  6. Anonymous3:10 AM

    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

    ReplyDelete
  7. Anonymous4:27 AM

    where can i found all modsecurity v2 byteid ?

    ReplyDelete
  8. @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/

    ReplyDelete