Wednesday, May 16, 2012

Protecting WordPress from script fishing attacks with Fail2Ban

SkyHi @ Wednesday, May 16, 2012

I posted some previous ideas on this that were okay, but they turned out to be less-than-idea solutions. They work, but one of the blogs I watch over is a bit busy, and having Fail2Ban watching the Apache access.log was putting excessive load on the CPU.
So here’s a nicer approach, but it needs a bit more fiddling:
As /etc/fail2ban/filters.d/apache-phpmyadmin.conf
[Definition]
failregex =  [[]client []] (File does not exist|script ').*(phpMyAdmin|phpmyadmin|dbadmin|mysql|myadmin|w00t|muieblackcat|mysqladmin).*
ignoreregex =
As /etc/fail2ban/filters.d/apache-wp-login.conf
[Definition]
failregex =  [[]client []] WP login failed.*
ignoreregex =
As /etc/fail2ban/filters.d/apache-wp-timthumb.conf
[Definition]
failregex =  [[]client []] (File does not exist|script ').*(timthumb\.php).*
ignoreregex =
The relevant sections of /etc/fail2ban/jail.local should be something like these. This allows a few failed logins, but only one attempt to hit a phpMyAdmin directory or the TimThumb exploit. But maxretry and findtime can be whatever you want.
[apache-wp-login]
enabled = true
port    = http,https
filter  = apache-wp-login
logpath = /var/log/apache*/*error.log
maxretry = 3
findtime = 120

[apache-phpmyadmin]
action = %(action_mwl)s
enabled = true
port    = http,https
filter  = apache-phpmyadmin
logpath = /var/log/apache*/*error.log
maxretry = 1
findtime = 60

[apache-wp-timthumb]
action = %(action_mwl)s
enabled = true
port    = http,https
filter  = apache-wp-timthumb
logpath = /var/log/apache*/*error.log
maxretry = 1
findtime = 60
So now all of the jails are watching error.log, which hopefully gets significantly less traffic than access.log. But we need to make sure WordPress logs the information we need.
If pretty permalinks is turned on, WP handles 404s and does not output to a log. Add a 404.php to the active theme that looks like this, or if there is already one, just add the error_log line:


And add this to the functions.php in your theme too, to handle the login attempts:
 // Log login errors to Apache error log
 add_action('wp_login_failed', 'log_wp_login_fail'); // hook failed login

 function log_wp_login_fail($username) {
  error_log("WP login failed for username: $username");
 }
Restart Fail2Ban server to pickup the changes, start some logging, and do some testing.
sudo service fail2ban restart
tail -n 100 -f /var/log/fail2ban.log








REFERENCES
http://blog.somsip.com/2012/02/using-fail2ban-to-protect-wordpress/
http://blog.somsip.com/2012/01/protecting-wordpress-from-script-fishing-attacks-with-fail2ban-more/
http://blog.somsip.com/2011/12/protecting-wordpress-from-script-fishing-attacks-with-fail2ban/