Securing Apache with mod_security

Now that the basic Apache configuration is working, let’s take some time to harden the installation. The module mod_security is really handy for this task. It is an application level firewall meaning that it will inspect incoming requests to the webserver and try to identify possible attacks like code injection, SQL injection and cross-site-scripting. As handy as this tool might be, it is not meant as a substitute for a secure PHP or Apache configuration, so you still need to take care not to open potential security holes there. If you followed my basic Apache and PHP setup you should be on the safe side, as the most exploited security holes have already been closed.

To be always up to date with mod_security I prefer to compile it myself. To do this we need to install some missing development files:

apt-get install libxml2-dev apache2-prefork-dev

Now we can go ahead and grab the latest sources from http://www.modsecurity.org (in this case version 2.1.2) and unpack them in your home directory:

tar -xvzf modsecurity-apache_2.1.2.tar.gz
cd modsecurity-apache_2.1.2/apache2

We need to define the location of our Apache home directory in the Makefile. Find the line top_dir = and set it to top_dir = /usr/share/apache2. Now you should be able to compile and install the module:

make
make install

Before we activate mod_security, we need to setup filtering rules. The current release of mod_security comes bundled with a sophisticated set of rules, which is called the core rule set. We can use these configuration files as starting point for our customized set. We will store the csutomized mod_security rules in /etc/apache2/mod_security:

mkdir /etc/apache2/mod_security
cp ~/modsecurity-apache_2.1.2/rules/*.conf /etc/apache2/mod_security/
cp ~/modsecurity-apache_2.1.2/rules/blocking/*.conf /etc/apache2/mod_security/

As you can see, first we copy the standard rule set to our new directory and next we overwrite some of the configuration files with config files which include versions of the rules which will block the traffic matching the rule.

Most of the configuration will be done in the file /etc/apache2/mod_security/modsecurity_crs_10_config.conf. So open this file and make the following modifications:

SecRuleEngine DetectionOnly
SecResponseBodyAccess Off
SecDefaultAction "phase:2,log,deny,status:500"
#SecServerSignature "Apache/2.2.0 (Fedora)"
SecAuditLog /var/log/apache2/modsec_audit.log
SecAuditLogRelevantStatus "^(?:5|4\d[^4])"
SecDebugLog /var/log/apache2/modsec_debug.log

The above configuration sets the path to the logfiles and most important it will start the module in detection mode. This means that the configured rules will not block an access, but log only. Without this logging step you will likely break some of your applications.

Now we need to activate the module and load all security rules. To do this we will create a file /etc/apache2/mods-available/security2.load which will load the mod_security module. It has the following contents:

LoadModule security2_module /usr/lib/apache2/modules/mod_security2.so

We also need a configuration file which will load all of our security rules. The files is named /etc/apache2/mods-available/security2.conf:

<IfModule mod_security2.c>
    Include /etc/apache2/mod_security/*.conf
</IfModule>

Now we can enable mod_security:

a2enmod security2
/etc/init.d/apache2 restart

After restarting the server, browse all your applications and try to simulate normal use. You could also leave the server for a couple of hours. In the meantime mod_security will log all requests that it would block into the file /var/log/apache2/modsec_audit.log. So, take a look at the logfile and identify all rules which are false positives. Meaning that these rules should not trigger for your applications to work. Example of a message:

--bf9af342-H--
Message: Warning. Pattern match "(?:\\b(?:\\.(?:ht(?:access|passwd|group)|www_?acl)|global\\.asa|httpd\\.conf|boot\\.ini)\\b|\\/etc\\/)" at ARGS:content. [id "950005"] [msg "Remote File Access Attempt. Matched signature </etc/>"] [severity "CRITICAL"]
Stopwatch: 1187386802219993 629097 (117984* 168889 -)
Producer: ModSecurity v2.1.2 (Apache 2.x)
Server: Apache

--bf9af342-Z--

Each rule has a unique id. In the above example the id is 950005. If we want to remove the rule with this id, we need to create a file /etc/apache2/mod_security/modsecurity_crs_99_customrules.conf:

SecRuleRemoveById 950005

You can also specify multiple rule ids or put the above configuration setting in any other Apache configuration file, for example inside a Location-directive so that the whitelisting will only apply to a specific URL-Location. You should disable the rules in a small context to keep the general ruleset strong.

When you are happy with the configuration you need to change in /etc/apache2/modsecurity_crs_10_config.conf the line:

SecRuleEngine On

which will set mod_security into active mode and now really block malicious requests.

Leave a Reply