Note: Rho’s excellent blog post pointed me in the right direction – credit where credit is due.
On my websites, I’ve seen a lot of scanning for vulnerable phpMyAdmin installations.
As a matter of policy, I don’t run phpMyAdmin on any Internet-facing web server. The scans won’t find anything, but the log entries are annoying so I decided to take action.
Some information about the attacks:
- The scans originate from a variety of sources, so an IP-address block will not work.
- The scans typically probe IP-addresses (not hostnames) for phpMyAdmin installations. We will use this to our advantage.
The scans cannot be prevented, but at least we can slow them down to make them less effective.
What do we need?
On CentOS / Red Hat Enterprise Linux, these are installed using the “httpd” and “mod_security” RPMs.
On Apache, it is common to use “Name-Based Virtual Hosting”. This technique allows you to run many websites on a single IP-address.
The first “Virtualhost” you define in Apache becomes the default host that is used if the request is made to the IP-address (http://188.8.131.52/phpMyAdmin) instead of the hostname (http://example.com/phpMyAdmin). Most probes will hit this default host as they use an IP-address instead of a hostname.
We will set up a ModSecurity rule on this Virtualhost to catch anyone looking for “phpmyadmin”, “phpMyAdmin” etc. This will require case-insensitive matching. I modified the SecRule in Rho’s blog entry by including a “to lowercase” function:
SecRule REQUEST_URI phpmyadmin t:lowercase,pause:5000,log,noauditlog,status:402,deny
The rule is now no longer case-sensitive and will catch all variations of upper- and lower-case letters.
My default virtualhost configuration looks like this:
# The first VirtualHost is special; it is the default # It is mostly accessed by IP-based clients (or port scanners) # Therefore, this is an ideal candidate for a "tarpit" or "honeypot" # # Allow Apache to access the DocumentRoot <Directory "/var/www/virtual/defaultsite/html"> Options None AllowOverride None Order Deny,Allow Allow from All </Directory> # Define the virtual host <VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/virtual/defaultsite/html ServerName default.example.com # Set up a tarpit for all those pesky phpMyAdmin scanners out there # Inspired by http://kill.devc.at/node/26 # <IfModule mod_security2.c> SecRuleEngine On SecDefaultAction log,allow,status:406,phase:2 SecRule REQUEST_URI phpmyadmin t:lowercase,pause:5000,log,noauditlog,status:402,deny SecDebugLog /var/log/httpd/modsec_tarpit.log SecDebugLogLevel 1 </IfModule> ErrorLog /var/log/httpd/defaultsite-error_log CustomLog /var/log/httpd/defaultsite-access_log common </VirtualHost>
If all is well (service httpd configtest), restart Apache (service httpd graceful) and watch the tarpit logfile:
[14/Aug/2010:00:58:49 +0200] [184.108.40.206/sid#2ba86c651138][rid#2ba3523ad573][/pHpMyAdMin] Access denied with code 402 (phase 2). Pattern match "phpmyadmin" at REQUEST_URI.
Good! The attacker was delayed for 5 seconds (5000 msec). You can now feel good about yourself, knowing that you have made the Internet a safer place ;-)
Remember that each tarpitted connection ties up an Apache child process for the duration of the delay. This may impact your web server, so keep an eye on those logs.