Tarpitting with Apache and mod_security2

Like any other superhero, I like to fight the evil in this world. At least on Sundays. Today's evil of choice were the incessant beatings my virtual server has to take from these stupid scans for a phpMyAdmin installation: [19/Aug/2007] "GET /phpmyadmin/main.php [19/Aug/2007] "GET /phpMyAdmin/main.php

Of course, it would be trivial with Apache to block this with a <LocationMatch> directive, but superheroes like me (just call me the Silver Surfer) always go, uhm, surf further.

First we prep our Debian server with mod_security. Since I am using Apache 2.2 which is not working with libapache2-mod-security because of a dependency problem, I decided to turn directly to mod_security2, the successor to the 1.x series.

So, let's follow the hint on the download page to add this to /etc/apt/sources.list

# Packages for Etch
deb http://etc.inittab.org/~agi/debian/libapache-mod-security2/etch ./

# Packages for Sarge
deb http://etc.inittab.org/~agi/debian/libapache-mod-security2/sarge ./

and do the Debian mantra:

apt-get update
apt-get install libapache2-mod-security2

To test whether my Apache is now secure (ha!), I hooked a trivial mod-security-basic file into my /etc/apache2/conf.d:

<IfModule mod_security2.c>
    SecServerSignature "Zanussi Machine 3.1415"

This line should make the hacker's life difficult as there are no known vulnerabilities for Zanussi. And indeed we see in the response headers:

Server: Zanussi Machine 3.1415 mod_perl/2.0.2 Perl/v5.8.8

which again proves that Perl can run on anything.

So what about these phpMyAdmin scans? We simply add a rule to delay each request for 5 seconds (\ line wrapper should be removed):

<IfModule mod_security2.c>
    SecRuleEngine On
    SecDefaultAction    log,allow,status:406,phase:2
    SecRule REQUEST_URI /phpMyAdmin \                        pause:5000,log,noauditlog,status:402,deny

    SecDebugLog /var/log/apache2/modsec_debug.log
    SecDebugLogLevel 0

For this purpose we have turned on the rule engine and have then defined an action which will be taken if a particular rule triggers but has no action defined. While I do not plan to have this, I decided to log the request, but allow it. Still I let the server return code 406 (Not Acceptable).

The rule language looks much cleaner than in the 1.x series and it always follows the same pattern:

  • First a variable coming from the request (or the response), be it a header, a URI parameter, the body or an internal variable is looked at,
  • then the condition (can also be a regexp) is tested on that variable, and if that is satisfied,
  • then a set of actions is taken.

In the case that the request URI contains /phpMyAdmin the server will wait for 5000 milliseconds, will log the request, but will refrain from writing a detailed audit.

Then I thought that it would be appropriate to return 402 (Payment Required) as status. Also superheroes have humor. On Sundays.

A final note: True, the above setup isnogood in the case of a DoS attack, but also for this scenario you can do something with mod_security2.

AsTMa fragment attached.

mod_security.atm807 bytes
Posted In

Where can I buy such a

Where can I buy such a super-secure Zanussi, with perl support? The local sales representative of Zanussi couldn't find out, is still wondering ...

Please give more details in your blog, to save the world from the evil!

Anonymous | Tue, 08/28/2007 - 10:00
rho | Tue, 08/28/2007 - 20:47

The steps shown here are

The steps shown here are really effective and makes a deep sense of knowledge to the viewers which requires a lot of skill I must congratulate you for this efforts.

autocad (not verified) | Sat, 01/29/2011 - 10:14

Re: Thank You

Dear Spammer,

No: I must thank you!

rho | Mon, 01/31/2011 - 21:38