Fail2Ban for Content Management Systems

I was setting up fail2ban recently, I noticed that my notes were outdated, and I decided to document the setup for current setups.  Despite what the title states, this can be used for anything as long as you know what logs are receiving entries and what attacks look like.  For example, I haven't played with Drupal in a while but I seem to recall the admin page looking something like:  ?q=user/login

With that information, we search the logs for repeated attempts, create a regex and now this works for Drupal as well.

If you haven't already installed iptables, here are the steps for enabling iptables for ports open on ssh, http, and https.

sudo apt-get install iptables-persistent

During the installation, we're going to receive the following question, enter Y:

Save current IPv4 fules? Y

When the install is finished, we're going to setup some rules:

sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -A INPUT -j DROP
sudo iptables-save > /etc/iptables/rules.v4

(on this last command, if you get "permission denied", sudo su, then execute that last command once more)

sudo apt-get install fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

We're going to insert the following near the bottom just below [asterisk-udp] but you can insert it into any part of that section in general.

[framework-CMS]
enabled = true
port = 80,443
protocol = tcp
filter = framework-CMS
logpath = /var/log/apache2/access.log
maxretry = 10
bantime = 86400

Save the file and exit.

Note: "maxretry" equals the number of failed attempts and "bantime" is one day.

Now we're going to create our fail2ban regex:

sudo nano /etc/fail2ban/filter.d/framework-CMS.conf

[Definition]

failregex = ^<HOST> - - \[.*\] "POST \/administrator/index.php.*$
                    ^<HOST> - - \[.*\] "POST \/wp-login.php.*$
                    ^<HOST> - - \[.*\] "POST \/xmlrpc.php.*$

ignoreregex =

Save the file and exit.

The first entry, administrator/index.php, is our Joomla login.
The second entry, wp-login.php, is our Wordpress login.
The final entry, xmlrpc.php, is a standard used with at least Joomla and Wordpress for a "standard" method of communication between different systems and is also a point of attack.
You could add additional lines here to parse the log for other regex like Drupal.  

With our regex setup, let's restart fail2ban:

sudo service fail2ban restart

Before we create failed login attempts, recognize that you could ban your IP which will lock your out for "bantime".  Be careful!  I would use another system on a different network.  If you're going through a firewall, you could ban the entire subnet.  Did I mention -- be careful?  ! 

Now let's create some failed login attempts.  If you exceed 10 attempts, you should get banned.  If you want to verify the regex is working correctly:

fail2ban-regex /var/log/apache2/access.log /etc/fail2ban/filter.d/framework-CMS.conf

The output:

Running tests
=============

Use failregex file : /etc/fail2ban/filter.d/framework-CMS.conf
Use log file : /var/log/apache2/access.log

Results

======

Failregex: 10 total
|- #) [# of hits] regular expression
| 4) [10] ^<HOST> - - \[.*\] "POST \/xmlrpc.php.*$
`-

Ignoreregex: 0 total

Date template hits:
|- [# of hits] date format
| [132] Day/MONTH/Year:Hour:Minute:Second
`-

We see 10 hits to xmlrpc.php

We can also look in the fail2ban log file:

tail -f /var/log/fail2ban.log

2018-06-18 10:47:03,896 fail2ban.actions: WARNING [framework-CMS] Ban x.x.x.x

I've removed the IP, replacing with x.x.x.x

You could also run:

sudo iptables -S

This will show you what addresses are currently banned as well.