September 1, 2016
Previously, I've shared how I caught and blocked a brute force attack on Wordpress xmlrpc.php. I'll use this attack as an example to explain how to write a custom filter and use it to automatically block an attacker.
Fail2ban is a software that watches log files and detect patterns in text. When a pattern is detected, it creates a firewall rule to block the attacker's IP address.
The first thing is to install Fail2ban:
sudo apt-get updatesudo apt-get install -y fail2ban
In my case, a Wordpress brute force attack on the
xmlrpc.php file, it can be
detected in the Apache's access log file:
$ sudo cat /var/log/apache2/access.log | grep xmlrpc.php184.108.40.206 - [26/Aug/2016:21:59:56 -0400] "POST /xmlrpc.php HTTP/1.0" 403 471 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
Indicators I use to identify the attack are:
POSTrequest - contains the payload, credentials
/xmlrpc.php- targeted vulnerability
403status code - failed attempt to login
I use RegExr to make sure my regular expression is correct:
The pattern I come up with is
^\S+ .+POST \/xmlrpc\.php HTTP.+ 403
Then I replace the
\S+ part, which stands for "a sequence of any
non whitespace character", with the Fail2ban
<HOST> token. The Fail2ban's
failregex now looks like this:
^<HOST> .+POST \/xmlrpc\.php HTTP.+ 403
Different operating systems or configurations might prefix log lines with additional information and requires to add
I create a new
xmlrpc-bruteforce.conf file in the
$ sudo nano /etc/fail2ban/filter.d/xmlrpc-bruteforce.conf# Fail2Ban filter for WordPress bruteforce through xmlrpc.php file#[INCLUDES]before = common.conf[Definition]failregex = ^<HOST> .+POST \/xmlrpc\.php HTTP.+ 403ignoreregex =
common.conf file allows the use of generic replacement patterns
Thankfully, Fail2ban comes with a testing tool that makes testing straightforward:
$ fail2ban-regex /var/log/apache2/access.log /etc/fail2ban/filter.d/xmlrpc-bruteforce.confRunning tests=============Use failregex file : /etc/fail2ban/filter.d/xmlrpc-bruteforce.confUse log file : /var/log/apache2/access.log# Results...Lines: 1720 lines, 0 ignored, 456 matched, 1264 missed
The test successfully shows that the pattern is found in 456 of 1720 lines
contained in the
To confirm, I run the test on a part of the file only, where I know how many occurences should be found.
Once the filter is created, I add a new jail by creating the
$ sudo nano /etc/fail2ban/jail.d/xmlrpc-bruteforce.conf[xmlrpc-bruteforce]enabled = true # rule is enablefilter = xmlrpc-bruteforce # given this filterlogpath = /var/log/apache2/access.log # watch this filemaxretry = 1 # and on first matchbanaction = iptables-allports # apply this banbantime = 604800 # for 1 weekprotocol = all # for any protocol
maxretry defines how many times a given IP address can match the filter before
being sent to jail. The above jail is pretty strict given that there's no
legitimate use of the file for this Wordpress installation.
To enable jails, Fail2ban has to reload:
$ sudo fail2ban-client reload2015-04-18 16:12:08,321 fail2ban.jail : INFO Jail 'xmlrpc-bruteforce' started
Fail2ban has created a new firewall rule on the first attempt (ESTABLISHED) and I can see dropped
traffic (SYN_SENT) with
$ tcptrack -i venet0 port 80...220.127.116.11:55646 18.104.22.168:80 SYN_SENT 4s 0 B/s22.214.171.124:41928 126.96.36.199:80 SYN_SENT 8s 0 B/s188.8.131.52:46015 184.108.40.206:80 SYN_SENT 5s 0 B/s220.127.116.11:59913 18.104.22.168:80 SYN_SENT 30s 0 B/s22.214.171.124:60861 126.96.36.199:80 SYN_SENT 23s 0 B/s188.8.131.52:54418 184.108.40.206:80 SYN_SENT 5s 0 B/s220.127.116.11:36830 18.104.22.168:80 SYN_SENT 18s 0 B/s22.214.171.124:49217 126.96.36.199:80 ESTABLISHED 1s 901 B/s...
1 Setup: Ubuntu 14.04.5 LTS, Fail2Ban v0.8.11, tcptrack v1.4.2 ↑