Block Brute Force Attacks on WordPress and Joomla using ModSecurity

WordPress and Joomla are probably the two most popular web apps that are massively used by end users to create fast websites. But that popularity also comes with high risks. That’s why today we will explore some ways to block brute force attacks on WordPress and Joomla using ModSecurity rules.

WP and Joomla are popular because they are easy to install, the learning curve is pretty fast, they are translated into lot of languages, and offer a fast and 1 click way to get your website running in just minutes.

And because this two pieces of software are two of the most popular ones, this leads to be two of the most attacked apps too. Brute force attacks are the most common attacks on this platforms.

Brute force attacks try to guess your user and password credentials in order to gain access to your private administrator area. On this post we will cover how to protect and stop brute force attacks on WordPress and Joomla using custom mod_security rules.

Install Mod_Security

In order to setup a protection to block brute force attacks on WordPress and Joomla you need to make sure that you are already running Mod_Security on your server. If you don’t have modsecurity installed, you can do it by following this guide: Install ModSecurity on cPanel

Step by Step: Block brute force attacks on WordPress and Joomla

Let’s create a file called bruteforce.conf on this location: /usr/local/apache/conf/bruteforce.conf

Type the following command:

nano -w /usr/local/apache/conf/bruteforce.conf

Then paste this content inside:

# WordPress & Joomla ModSecurity Brute Force Rules
# -----------------------------------------------------------------------------
# TX.max_requests - # of requests allowed during x period of time
# TX.requests_ttl - time in seconds
# TX.block_ttl - block time in seconds
# -----------------------------------------------------------------------------

SecRequestBodyAccess On
SecDataDir /tmp
SecAction "phase:1,pass,setvar:TX.max_requests=6,setvar:TX.requests_ttl=180,setvar:TX.block_ttl=900,initcol:ip=%{REMOTE_ADDR},nolog,id:5001000"
SecRule IP:blocked "@eq 1" "phase:1,drop,log,id:5001001"

# WordPress Anti Brute Force Rules
<LocationMatch "/wp-login.php">
SecAction "phase:2,chain,nolog,id:5001002"
SecRule REQUEST_METHOD "^POST$" "chain"
SecRule ARGS_POST_NAMES "^log$" "chain"
SecRule ARGS_POST_NAMES "^pwd$" "chain"
SecAction "setvar:ip.request_count=+1,expirevar:ip.request_count=%{TX.requests_ttl}"

SecRule IP:request_count "@ge %{TX.max_requests}" "phase:2,drop,setvar:ip.blocked=1,expirevar:ip.blocked=%{TX.block_ttl},log,msg:'Bloqueado por %{TX.block_ttl} segundos',id:5001003"

# Joomla Anti Brute Force Rules
<LocationMatch "/administrator/index.php">
SecAction "phase:2,chain,nolog,id:5001012"
SecRule REQUEST_METHOD "^POST$" "chain"
SecRule ARGS_POST_NAMES "^username$" "chain"
SecRule ARGS_POST_NAMES "^passwd$" "chain"
SecRule ARGS_POST:option "^com_login$" "chain"
SecRule ARGS_POST:task "^login$" "chain"
SecAction "setvar:ip.request_count=+1,expirevar:ip.request_count=%{TX.requests_ttl}"

SecRule IP:request_count "@ge %{TX.max_requests}" "phase:2,drop,setvar:ip.blocked=1,expirevar:ip.blocked=%{TX.block_ttl},log,msg:'Bloqueado por %{TX.block_ttl} segundos',id:5001013"

# Old Joomla installations
<LocationMatch "/administrator/index.php">
SecAction "phase:2,chain,nolog,id:5001022"
SecRule REQUEST_METHOD "^POST$" "chain"
SecRule ARGS_POST_NAMES "^usrname$" "chain"
SecRule ARGS_POST_NAMES "^pass$" "chain"
SecAction "setvar:ip.request_count=+1,expirevar:ip.request_count=%{TX.requests_ttl}"

SecRule IP:request_count "@ge %{TX.max_requests}" "phase:2,drop,setvar:ip.blocked=1,expirevar:ip.blocked=%{TX.block_ttl},log,msg:'Bloqueado por %{TX.block_ttl} segundos',id:5001023"

Loading Anti Brute Force rules

Now let’s configure ModSecurity to load those brute force protection rules, run this command:

echo "Include /usr/local/apache/conf/bruteforce.conf" >> /usr/local/apache/conf/modsec2.user.conf

Restart Apache to apply changes:

service httpd restart

The resulsts of this brute force protection for WordPress and Joomla will be logged at Apache error log
Los resultados del bloqueo podremos verlos en el log de Apache. Tras 5 intentos fallidos de conexión la IP responsable será bloqueada:

Before wp-login.php login attempts were looking like this:

111.111.111.111 - - [01/Dec/2016:09:31:37] "POST /wp-login.php HTTP/1.0" 200 
222.222.222.222 - - [01/Dec/2016:09:31:38] "POST /wp-login.php HTTP/1.0" 200 
111.111.111.111 - - [01/Dec/2016:09:31:39] "POST /wp-login.php HTTP/1.0" 200

After setting up the brute force rules, you should notice 406 status on each brute force attack:

111.111.111.111 - - [01/Dec/2016:09:35:41] "POST /wp-login.php HTTP/1.0" 406 -
222.222.222.222 - - [01/Dec/2016:09:35:43] "POST /wp-login.php HTTP/1.0" 406 -
111.111.111.111 - - [01/Dec/2016:09:35:45] "POST /wp-login.php HTTP/1.0" 406 -

If this rules cause you any problems, can be deactivated by editing /usr/local/apache/conf/modsec2.user.conf file, and then remove the following line:

Include /usr/local/apache/conf/bruteforce.conf

Then restart Apache to apply changes:

service httpd restart

That’s all, now you know anothe way to block brute force attacks on WordPress and Joomla. Remember we’ve also written about how to install Comodo WAF on cPanel, which also includes very good Brute Force protection rules for common CMS like WP and Joomla.

About the Author: Santiago Borges

Experienced Sr. Linux SysAdmin and Web Technologist, passionate about building tools, automating processes, fixing server issues, troubleshooting, securing and optimizing high traffic websites.

1 Comment

  1. We found these rules really useful.

    Two things:
    (1) The code contains 3x but these were not closed so we had to add to the end of each section.
    (2) Would it be possible to extend the WordPress code to protect the xmlrpc.php file from flooding? Do you know if it uses similar arguments?

    Thanks very much!

Leave a Reply

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