Dev Notes

Various Cheat Sheets and Resources by David Egan/Carawebs.

Fail2Ban and WordPress


Fail2Ban, Security, Sysadmin, WordPress
David Egan

Fail2ban is generally used to prevent brute force break-in attempts against SSH servers. These attempts typically come from automated scripts attempting multiple username/password combinations. Fail2ban acts by automatically identifying and acting against possible break-in attempts.

For SSH, you could cut these kind of attacks off by disallowing password login, requiring server administrators to connect by means of a public/private key pair. You might also use a non-standard port for SSH connections - but don’t rely on this alone!

Fail2ban helps to secure SSH connections by dropping the connection after a defined number of unsuccessful login attempts.

Fail2ban is not an excuse to use weak authentication methods. You should protect important services with public/private authentication and/or very strong passwords.

How Fail2ban Works

Fail2ban is basically a sin bin for hosts. It scans log files (e.g. /var/log/auth.log) and bans IP addresses that cause multiple authentication errors.

When Fail2ban detects that the number of failed login attempts from an IP have exceeded the pre-defined threshold, it updates the system firewall rules to reject new connections from those IP addresses for a set length of time. When the ban time is up, the ban is lifted.

Fail2ban allows you to configure:

  • A white-list of IP addresses to avoid accidental lockouts
  • The threshold number of unsuccessful logins
  • The time period over which malicious attempts are considered
  • The length of stay in the sin-bin
  • The precise actions taken - e.g. you can set up an email detailing RIPE data for each ban

Get Fail2ban

On Ubuntu, this is very simple:

sudo apt-get update
sudo apt-get install fail2ban

Fail2ban Configuration

Fail2ban config files are located in /etc/fail2ban.

There is a default config file: /etc/fail2ban/jail.conf - but DO NOT edit this, since the file can be modified by upgrades.

Copy the file:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

You can now configure Fail2ban by editing jail.local:

sudo nano /etc/fail2ban/jail.local

Within this file you can:

  • Create an ignoreip whitelist
  • Set the bantime
  • Set the conditions to determine illegitimate users: findtime and maxretry i.e. how many retries are allowed over a set time period
  • Set the MTA and email address if you are adding email notifications to your Fail2ban action
  • Set the action that Fail2ban takes when an illegitimate login attempt is detected

WordPress & Fail2ban

Beyond SSH, “brute force” activity focusing on WordPress login pages (e.g. yoursite.com/wp-admin) is very common. You could lock down access to wp-login.php by white-listing IP addresses. However, this isn’t always possible:

  • The site might be member-focused, with lots of members logging in from variable IP addresses
  • The client/site administrator may not have a fixed IP address

The benefit of using Fail2ban is that you can protect multiple sites on a server. Fail2ban is actively developed and maintained, and you should probably be running it on your Linux box anyway.

Unsuccessful WordPress log in attempts are not normally logged to the server logfiles - so they are not picked up on by Fail2ban.

To set up Fail2ban with WordPress you need to:

  1. Add malicious login attempts to the auth.log for all managed WordPress installations
  2. Properly configure Fail2ban to act on unauthorized login attempts - add the IP of malicious users to a firewall “deny” directive

Add Failed Login Attempts to auth.log

Add WP fail2ban as a must-use plugin. This writes unsuccessful login attempts to /var/log/auth.log.

By defining the appropriate constant in wp-config.php, the plugin can also block WordPress user enumeration attempts.

User enumeration is when a quesry string like http://yoursite.com/?author=1 is entered. On an unprotected WordPress site, this will return an archive page for user with an ID of 1 (usually the first administrative user), displaying the Username. This gives a would-be hacker the benefit of knowing your username.

If using the WP fail2ban plugin, this is easily blocked. Just add this line to wp-config.php:

define( 'WP_FAIL2BAN_BLOCK_USER_ENUMERATION', true );

For academic interest, here’s how this is achieved within the plugin:

<?php
if (defined('WP_FAIL2BAN_BLOCK_USER_ENUMERATION') && true === WP_FAIL2BAN_BLOCK_USER_ENUMERATION) {
  add_filter( 'redirect_canonical',
  function($redirect_url, $requested_url)
  {
    if (intval(@$_GET['author'])) {

      openlog();
      \syslog(LOG_NOTICE,'Blocked user enumeration attempt from '.remote_addr());
      bail();

    }

    return $redirect_url;

  }, 10, 2);

}

Set Up a Fail2ban Filter

A Fail2ban filter contains a regular expression which is used to define a logged event as a break-in attempt.

Filters should be added to the /etc/fail2ban/filter.d directory. The regexes in the filter MUST match the log entries for failed login attempts. The WP fail2ban plugin has a sample filter - this can be added to /etc/fail2ban/filter.d/wordpress.conf:

cd /etc/fail2ban/filter.d
wget http://plugins.svn.wordpress.org/wp-fail2ban/trunk/wordpress.conf

Set Up a WordPress Jail

A WordPress jail can be created for Fail2ban. The jail is defined in a configuration file located in the directory /etc/fail2ban/jail.d. For example:

sudo nano /etc/fail2ban/jail.d/wordpress.conf

# Add the following to the jail config file:
[wordpress]
enabled = true
filter = wordpress
logpath = /var/log/auth.log
port = http,https

The jail configuration sets the filter that will be used, as well as the path to the log file.

Fail2Ban Action

When the failed login attempt has been logged, a Fail2ban action should be configured.

There are several default actions available in /etc/fail2ban/jail.local. The most basic action involves adding a new firewall rule, but you can configure email notifications as part of the Fail2ban action.

Unban an IP Address

To unban an IP address from the WordPress Fail2Ban jail:

sudo fail2ban-client set wordpress unbanip 11.111.11.11

Troubleshooting

Make sure that the regex in the WordPress filter matches the string that is written into the log file on authentication failure.

It can be useful to run tail -f /var/log/auth.log and run a few failed logins. You’ll see the log entries in real time, and can cross reference this with the regex in /etc/fail2ban/filter.d/wordpress.conf.

Automation

It is a good idea to apply these measures to all WordPress sites that are hosted on public-facing servers. Once Fail2ban has been configured for a server, the logging functionality just needs to be enabled for all new sites. If you have a site creation script, the WP Fail2ban mu-plugin could be added automatically whenever a new site is created.

Logging: Repeated Entries

The Rsyslog daemon should be configured to turn OFF the $RepeatedMsgReduction configuration parameter. To achieve this, amend /etc/rsyslog:

# Use sed to amend the config setting
sudo sed -i 's/RepeatedMsgReduction\ on/RepeatedMsgReduction\ off/' /etc/rsyslog.conf

…alternatively, edit /etc/rsyslog.conf manually.

By default in Ubuntu 14.04, repeat messages are suppressed in the rsyslog daemon. This can allow attackers to slip through - we need the consecutive failed authentication messages to appear in the log. The rsyslog project team actually recommend setting this parameter to “off”.

My testing has shown that with repeat message suppression turned on, Fail2Ban is less effective at banning offenders - repeat messages don’t seem to be counted if they come through straight after the previous attempt. I found this very confusing until I realised that the RepeatedMsgReduction should be turned off.

After this amendment, restart the rsyslog daemon:

sudo service rsyslog restart

Alternative WordPress Protection: Limit Login Attempts

Limit Login Attempts is a very useful plugin that basically limits login attempts (as you’d expect!). It provides a simple interface that allows you to control the lockout time, number of retries allowed etc.

Whilst extremely useful, the plugin is not actively maintained (it has more than 1 million downloads, but was last updated 3 years ago).

Resources


comments powered by Disqus