Detect and Block WordPress Brute Force Login Attacks

If you run a wordpress blog these days, you are likely to experience brute force attacks where nefarious individuals attempt to break in to your website by quickly a list of userids and passwords against your wp-login.php.  Here’s how I automated detection and blocking of WordPress brute force login attacks.

Detecting a WordPress Brute Force Attack

One can typically detect a wordpress brute force attack by parsing through your webserver’s access_log file.  The access_log file records all of the access requests that a web server handles.  A brute force attack typically will have frequent and numerous attempts to the wp-login.php file as shown below:


Example:  In the access_log file below, we detect a brute force login attack on our WordPress blog.  We detected it by noticing frequent and constant requests to the wp-login.php file.

31.192.210.159 - - [11/Sep/2014:02:01:43 +0000] "POST http://www.uptimemadeeasy.com/wp-login.php HTTP/1.1" 200 3389 "http://www.uptimemadeeasy.com/wp-login.php" "Mozilla/5.0 (Linux; U; Android 2.2) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
31.192.210.159 - - [11/Sep/2014:02:01:44 +0000] "POST http://www.uptimemadeeasy.com/wp-login.php HTTP/1.1" 200 3389 "http://www.uptimemadeeasy.com/wp-login.php" "Mozilla/5.0 (Linux; U; Android 2.2) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
31.192.210.159 - - [11/Sep/2014:02:01:45 +0000] "POST http://www.uptimemadeeasy.com/wp-login.php HTTP/1.1" 200 3389 "http://www.uptimemadeeasy.com/wp-login.php" "Mozilla/5.0 (Linux; U; Android 2.2) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
31.192.210.159 - - [11/Sep/2014:02:01:47 +0000] "POST http://www.uptimemadeeasy.com/wp-login.php HTTP/1.1" 200 3389 "http://www.uptimemadeeasy.com/wp-login.php" "Mozilla/5.0 (Linux; U; Android 2.2) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
31.192.210.159 - - [11/Sep/2014:02:01:49 +0000] "POST http://www.uptimemadeeasy.com/wp-login.php HTTP/1.1" 200 3389 "http://www.uptimemadeeasy.com/wp-login.php" "Mozilla/5.0 (Linux; U; Android 2.2) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
31.192.210.159 - - [11/Sep/2014:02:01:50 +0000] "POST http://www.uptimemadeeasy.com/wp-login.php HTTP/1.1" 200 3389 "http://www.uptimemadeeasy.com/wp-login.php" "Mozilla/5.0 (Linux; U; Android 2.2) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
31.192.210.159 - - [11/Sep/2014:02:01:51 +0000] "POST http://www.uptimemadeeasy.com/wp-login.php HTTP/1.1" 200 3389 "http://www.uptimemadeeasy.com/wp-login.php" "Mozilla/5.0 (Linux; U; Android 2.2) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
31.192.210.159 - - [11/Sep/2014:02:01:52 +0000] "POST http://www.uptimemadeeasy.com/wp-login.php HTTP/1.1" 200 3389 "http://www.uptimemadeeasy.com/wp-login.php" "Mozilla/5.0 (Linux; U; Android 2.2) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
31.192.210.159 - - [11/Sep/2014:02:01:54 +0000] "POST http://www.uptimemadeeasy.com/wp-login.php HTTP/1.1" 200 3389 "http://www.uptimemadeeasy.com/wp-login.php" "Mozilla/5.0 (Linux; U; Android 2.2) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
31.192.210.159 - - [11/Sep/2014:02:01:55 +0000] "POST http://www.uptimemadeeasy.com/wp-login.php HTTP/1.1" 200 3389 "http://www.uptimemadeeasy.com/wp-login.php" "Mozilla/5.0 (Linux; U; Android 2.2) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"

Typically in an event like this, I lookup the IP address in the ARIN database as I showed in a previous article:  What Personal Information Can You Get From Your Web Server?  Frequently, I find that the address is from APAC or RIPE addresses.

Blocking Brute Force Login Attacks with Iptables

Obviously, we do not want to let this address continue to pound our wp-login.php with failed logins.  We need to block it.  One method that we can use to block this attack is to add a rule into iptables to block traffic from this Ip Address.  

Example:  Block an Attackers IP Address in iptables.  

$ sudo iptable -A INPUT -s 31.192.210.159/32 -j DROP

This rule will start blocking the WordPress brute force attack.  As fun as that was, it may get a bit laborious to watch and do this manually.  We can create a script to check for these brute force attacks and block them automatically.

Automating Brute Force Attack Detection and Blocking with a Script

So, in an effort to automate my WordPress brute force attack detection and blocking, I wrote the script below.  It will log events using the syslog facility and text me when it detects an event.  Hopefully, it will help somebody else.

#!/bin/bash
# Capture the input variables
ACCESSLOG=$1
THRESHOLD=$2

# Restart iptables to be sure that only saved rules are recreated later
/sbin/service iptables restart

# First, we need to get the last 1 hour of transaction the logs:
# get the line number from the access_log file 1 hour ago.
HOURAGO=`date +%d/%b/%Y:%H -d "1 hour ago"`

# Now, get the line from the access_log from one hour ago
LINENUM=`/bin/grep -n ${HOURAGO} ${ACCESSLOG} | head -1 | awk -F':' '{print $1}'`

# Use the line number from 1 hour ago, to get all the transactions from
# then until now into a temporary log
TMPLOG=.tmpaccess_log_lasthourreport_`date +%d-%b-%Y-%H`.log
/bin/sed -n "${LINENUM},\$p" ${ACCESSLOG} > $TMPLOG

# Now, get all of the IP Addresses that have accessed wp-login.php
IPADDRESSES=(`/bin/grep wp-login.php ${TMPLOG} | /bin/awk '{print $1}' | sort | uniq -c | sort -rn | awk '{printf "%s:%s\n", $1, $2}'`)

# Now that we have our list of addresses, we need to create iptables rules for the eggregious offenders - those over our threshold

for i in "${IPADDRESSES[@]}"
do
 TIMES=`/bin/echo $i | /bin/awk -F":" '{print $1}'`
 IPADDRESS=`/bin/echo $i | /bin/awk -F":" '{print $2}'`
 if [ ${TIMES} -ge ${THRESHOLD} ]
 then
 echo "Attack Detected: ${IPADDRESS} had ${TIMES} instances! "
 # Verify that the address hasn't already been added to iptables
 if ! grep -q ${IPADDRESS} /etc/sysconfig/iptables
 then
 # Add an iptables firewall rule
 /sbin/iptables -I INPUT -s ${IPADDRESS} -j DROP
 # Log this event using the syslog facility
 /usr/bin/logger -p local0.info -t "- $0 detected WordPress brute force attack from ${IPADDRESS}. Blocking this address in iptables."
 # Send an alert to my cell phone
 /bin/echo "`hostname` WordPress Brute force attack detected from ${IPADDRESS}." | /usr/bin/mutt -s "WP Brute Force Attack Detected" 8011234567@txt.att.net
 fi
 fi
done

# Save our rules!
/sbin/service iptables save

# Now for a little cleanup
rm -f ${TMPLOG}

Here is how it is run:

$ sudo ./findattacks.sh <path to access_log file> <threshold>

where threshold is the number of matching lines in the access_log before it is enough to trigger a block.

Remember to cron it to make it automated:

*/20 * * * * /usr/local/sbin/findattacks.sh /var/log/varnish/varnishncsa.log 200

This script has protected me from a bunch of brute force attacks.  I hope that this script helps you Detect and Block WordPress Brute Force Login Attacks on your website.

The following two tabs change content below.
Jeff has 20 years of professional IT experience, having done nearly everything in his roles of IT consultant, Systems Integrator, Systems Engineer, CNOC Engineer, Systems Administrator, Network Systems Administrator, and IT Director. If there is one thing he knows for sure, it is that there is always a simple answer to every IT problem and that downtime begins with complexity. Seasoned IT professional by day, Jeff hopes to help other IT professionals by blogging about his experiences at night on his blog: http://uptimemadeeasy.com. You can find Jeff on or LinkedIn at: LinkedIn or Twitter at: Twitter

Latest posts by Jeff Staten (see all)

3 comments for “Detect and Block WordPress Brute Force Login Attacks

  1. February 4, 2015 at 6:33 am

    Thank you for the script. Is there any way to adapt the script for a server running cPanel? The script should be able to check all the apache log files for all the users on server. The path would be /usr/local/apache/domlogs/*

    Please let me know.

    Regards,

  2. April 1, 2015 at 8:41 pm

    I am sure that there is a way to use the script with cpanel. You will have to work out the details though. Sorry.
    Jeff

  3. July 11, 2015 at 9:17 am

    Tnx!

Leave a Reply

Your email address will not be published. Required fields are marked *