How-to : Mod-security 2 set-up for Apache 2

Mod-security is a security proxy for Apache. It adds a frontal layer filtering unwanted clients, malformed packets and malicious requests.

It is especially usefull if your website is dynamic, involving php, sql, javascript, etc. With such a complex environment, as you can never be sure that your website is not vulnerable or up-to-date enough, something like mod-security provides an interesting extra-security layer.

Due to license issues, mod-security is no more shipped with Debian – it was until Debian Sarge.

Fortunately, the Debian maintainer continue to provide some packages on his website.

So, the easy way to set up mod-security on your Debian system is to add this line in your /etc/apt/source.list file :

$ echo "deb etch/" >> /etc/apt/source.list

Then type in the usual sequence :

$ aptitude update && aptitude install libapache-mod-security2

You could also download the source from the official website.

Once it is done, comes the configuration part. The configuration is critical because any mistake on it will make it at best useless, or at worst blocking your website.
You have the choice between creating your rules from scratch or getting some ready made.
Creating your rules will require a lot of time and expertise in the http protocol, php, sql, and any other service that you offer with Apache.
That was not really my case, so I started to look for some ready made rules on google. I could not get good ones. Most of tutorial gives only some very basic and incomplete rules : useless. I found a good paper, notably containing some specific rules for WordPress, but the rules were written for mod-security v1 whereas it is now in its second version.
Oh, did I forget to tell you ? Most of the syntax was changed between the two versions !!! Not very nice, even if it was worth doing it.

Finally, I came to find a way with the rules provided by this website, Got Root ?. They provide quite up-to-date rules, with a delay of 30 days subscription-free, which is quite acceptable for what I want to do. After all, Php exploits and Sql injection technics don’t change every day.

The rules are also complete and spread over several files, one for each category in : generic rules, blacklist, usergents, proxies, rootkits…

We can fetch them with a little script. They suggest to add it as a cron job, but you should not, except if you don’t mind that your website becomes unavailable ! These rules always require testing, some of them may be broken or require customizing… be careful and always check what’s inside the rule files !

Here is the small script,, that I made to retrieve the rules and put them in the right directory :


if [ -e apache2-gotrootrules-modsec2.0-latest.tar.gz ]
tar -xzvf apache2-gotrootrules-modsec2.0-latest.tar.gz -C /etc/apache2/modsecurity/
rm apache2-gotrootrules-modsec2.0-latest.tar.gz
/etc/init.d/apache2 restart

Make it executable and run it :

# chmod +x
$ ./

Now, let’s edit the /etc/apache2/apache2.conf file.

Just before these lines (probably at the bottom of the file) :

# Include the virtual host configurations:
Include /etc/apache2/sites-enabled/

Add these :

#Turn the filtering engine On or Off
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off

# Handling of file uploads
# TODO Choose a folder private to Apache.
# SecUploadDir /opt/apache-frontend/tmp/
SecUploadKeepFiles Off

# Maximum request body size we will
# accept for buffering
SecRequestBodyLimit 131072
# Store up to 128 KB in memory
SecRequestBodyInMemoryLimit 131072
# Buffer response bodies of up to
# 512 KB in length
SecResponseBodyLimit 524288

SecDebugLog /var/log/apache2/modsec_debug.log
SecDebugLogLevel 0
# Serial audit log
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus ^5
SecAuditLogParts ABIFHZ
SecAuditLogType Serial
SecAuditLog /var/log/apache2/modsec_audit.log

#should mod_security inspect POST payloads
#SecRuleScanPOST On

# by default log and deny suspicious requests with HTTP status 500
SecDefaultAction log,auditlog,deny,status:403,phase:2,t:none

#First, add in your exclusion rules:
#These MUST come first!
Include /etc/apache2/modsecurity/exclude.conf

#Application protection rules
Include /etc/apache2/modsecurity/rules.conf

#Comment spam rules
Include /etc/apache2/modsecurity/blacklist.conf

#Bad hosts, bad proxies and other bad players
Include /etc/apache2/modsecurity/blacklist2.conf

#Bad clients, known bogus useragents and other signs of malware
Include /etc/apache2/modsecurity/useragents.conf

#Known bad software, rootkits and other malware
Include /etc/apache2/modsecurity/rootkits.conf

#Signatures to prevent proxying through your server
#only rule these rules if your server is NOT a proxy
#Include /etc/apache2/modsecurity/proxy.conf

#Additional rules for Apache 2.x ONLY!  Do not add this line if you use Apache 1.x
Include /etc/apache2/modsecurity/apache2-rules.conf

As you can see, we just include the rule files we just downloaded. You can easily activate or deactivate some to fit your needs.

You will probably notice that there is a performance impact after activating mod-security – not so big to me, but it also depends on your traffic. It is up to you to optimize the number of activated rules to make it faster.

If some page appear to be blocked, check the /var/log/apache2/error.log for something like :

[Fri Jul 11 19:33:08 2008] [error] [client] ModSecurity: Access
denied with code 500 (phase 2). Match of "rx ^HTTP/(0\\\\.9|1\\\\.0|1\\\\.1|1\\
\\.2)$" against "REQUEST_PROTOCOL" required. [id "340000"] [msg "Bad HTTP Proto
col"] [severity "ALERT"] [hostname ""] [uri "/"] [unique_id "72F
col"] [severity "ALERT"] [hostname ""] [uri "/"] [unique_id "72F

The ID number of the blocking rule is given. Just grep to find the faulty rule and correct / deactivate it :

$ grep 340000 /etc/apache2/modsecurity

Regxp knowledge required ! :D