10+ Ways to Stop WordPress Brute Force Attacks

and published
WordPress Brute Force Prevention

Just like any other hugely popular content management system WordPress doesn’t have a great reputation when it comes to security, mainly because the people who use it don’t care, or don’t have a clue about hardening their WordPress website.

Thankfully WordPress is now more secure out of the box compared to earlier releases and the team at WordPress are now pretty snappy when it comes to patching WordPress exploitable vulnerabilities. Since the release of version 3.7, WordPress features an automatic updater which makes patching these vulnerabilities much quicker than before.

The Weakest Link

Hackers do, and will always look for the weakest link… brute force cracking is on the increase as computing power becomes faster and cheaper. WordPress is now harder than ever, but sadly as WordPress security measures improve the users that use their platform do not, unless they have pass experiences of being hacked.

WordPress receives regular updates to ensure that its secure but the problem of administrators remain, without offending people to much, a far majority of users under estimate the importance of security and they become the weakest link.

Brute force attacks rely on you being the weakest link, from the moment that you install WordPress using a weak username and password, your simply become the weakest link. However, using a strong password doesn’t necessary mean your website can’t be hacked, with brute force attacks, unless you’re using a SUPER DUPER! STRONG password, it’s just a matter of time.

What is a Brute Force Attack?

In cryptography, a brute-force attack, or exhaustive key search, is a cryptanalytic attack that can, in theory, be used against any encrypted data[1] (except for data encrypted in an information-theoretically secure manner). Such an attack might be used when it is not possible to take advantage of other weaknesses in an encryption system (if any exist) that would make the task easier. It consists of systematically checking all possible keys or passwords until the correct one is found. In the worst case, this would involve traversing the entire search space.

Create a Unique Administrator Username

When creating an administrator account for WordPress you should never use the username ‘admin’ or anything that resembles that role.

Example, never use usernames like this:

  • Admin
  • ADmIn
  • ADM1N
  • 4dm1n
  • Administrator
  • AdMiNistrator
  • Ad1min1strat0r
  • AdminIstration
  • Manager
  • God
  • Superadmin
  • Webmaster
  • Boss
  • SiteAdmin
  • Editor
  • TopAdmin

WordPress Brute Force hackers will often use a common list of username and passwords, before proceeding onto a broader search using a dictionary attack, and then onto a far more complex attack that tests for complex passwords.

Ideally and for advanced security you should opt to use a random string based username with characters with lower, and upper case characters mixed in with numbers. Treat your username as equally as important as your website’s password.

Creating a Strong Complex Password

The topic of password strengths is a huge topic and I’ll go as deep as I need to, but I simply don’t have the time, or energy to cover everything. When creating a strong password you should never use any singular dictionary word, combined dictionary words, or even long sentences using dictionary words as these remain the easiest to crack. It’s also worth noting that using any or a combination of dictionary words that are mixed with numbers or symbols is also considered insecure e.g elitemonster being el1t3m0nst3r.

One of my online buddies Stephen Ostermiller has developed an awesome password strength website that explains the possibility of password length being cracked and how long it would take using various super computers, clusters and desktop computers.

Taken from Steve’s site this should give you a better indication on the different type of passwords and their strengths:

Random Passwords
  • nsH=y’cEy!
  • =qzOB;8K;i
  • >V]wHh,-S!
  • \”J5D]&rtt
  • >jQn$5}0*o
  • SQ{Xd)]AO?
  • %[email protected]\x2Q7&
  • 4VY#nLKJ?E
  • W_y=[])L”;
  • ZeUy0W [mm
Writable Passwords
  • WC3eGMDFpZm8
  • PBrEP3TxLncN
  • YnpLzGtExYL5
  • 8eJXwP9tAGFP
  • ezdPPanfR4df
  • wzT9f4L4Nkci
  • gKMMCn2TARqJ
  • zMxaPnfX6gad
  • THgrtPZhGwjx
  • 4CfK8izPGyp2
Shiftless Passwords
  • gcq590dl8h;x
  • h]f n5vwgs]2
  • ‘583awcw;x0h
  • hl2b.9ye7m[e
  • q.\ks22wc’,e
  • ,3mw 1;70cpb
  • 28[=r4y7-d3t
  • ]vm r`m6;gxy
  • 5tgv 26/0yay
  • d5 3/2ll7g=y
Fake Word Passwords
  • guiniorpurnaciattlerru
  • zabrilargueffowboze
  • gigeontaggetunjurni
  • seendivickirrockiggi
  • flagoobuphisraeliurgi
  • griexpecruisliggepaibe
  • troptiowhestunsudepa
  • senazterrillippebo
  • stylizascangantutuappea
  • fredgemnaloobinglenche
Common Words Password
  • volumes waldo durable bind papa
  • barges witches cathy alter alpha
  • varying gray slide hidden reforms
  • hits swoop appear dynasty impulse
  • comment silky logged binary raising
  • cast tippy counts neglect revenge
  • shove mart bison hoping inputs
  • skipped bug tune froze theirs
  • deep tape genetic epithet pork
  • strike dealt nominal whose burly
Crack Time – Random Passwords
95 possible letters, numbers, and symbols Average time to crack based on number of guesses per second
Size Possible combinations 1 trillion (expected future capability) 100 billion (large distributed system) 1 billion (distributed system or supercomputer) 100 million (small distributed system) 1 million (single computer)
5 7.74 billion instant instant 4 seconds 39 seconds 1 hour
6 735 billion instant 4 seconds 6 minutes 1 hour 4 days
7 69.8 trillion 3 seconds 6 minutes 10 hours 4 days 1 year
8 6.63 quadrillion 6 minutes 9 hours 1 month 1 year 1 century
9 630 quadrillion 9 hours 1 month 10 years 1 century 100 centuries
10 59.9 quintillion 1 month 9 years 9 centuries 95 centuries
11 5.69 sextillion 9 years 9 centuries 902 centuries
12 540 sextillion 9 centuries 857 centuries
13 51.3 septillion 814 centuries
14 4.88 octillion
Crack Time – Writable Passwords
50 possible letters, and numbers Average time to crack based on number of guesses per second
Size Possible combinations 1 trillion (expected future capability) 100 billion (large distributed system) 1 billion (distributed system or supercomputer) 100 million (small distributed system) 1 million (single computer)
6 15.6 billion instant instant 8 seconds 1 minute 2 hours
7 781 billion instant 4 seconds 7 minutes 1 hour 5 days
8 39.1 trillion 2 seconds 3 minutes 5 hours 2 days 8 months
9 1.95 quadrillion 2 minutes 3 hours 11 days 4 months 31 years
10 97.7 quadrillion 1 hour 6 days 2 years 15 years 15 centuries
11 4.88 quintillion 3 days 9 months 77 years 8 centuries 774 centuries
12 244 quintillion 5 months 39 years 39 centuries 387 centuries
13 12.2 sextillion 19 years 19 centuries
14 610 sextillion 10 centuries 968 centuries
15 30.5 septillion 484 centuries
16 1.53 octillion
Crack Time – Shiftless Passwords
48 possible letters, numbers, and symbols Average time to crack based on number of guesses per second
Size Possible combinations 1 trillion (expected future capability) 100 billion (large distributed system) 1 billion (distributed system or supercomputer) 100 million (small distributed system) 1 million (single computer)
6 12.2 billion instant instant 6 seconds 1 minute 2 hours
7 587 billion instant 3 seconds 5 minutes 49 minutes 3 days
8 28.2 trillion 1 second 2 minutes 4 hours 2 days 5 months
9 1.35 quadrillion 1 minute 2 hours 8 days 3 months 21 years
10 64.9 quadrillion 54 minutes 4 days 1 year 10 years 10 centuries
11 3.12 quintillion 2 days 6 months 49 years 5 centuries 494 centuries
12 150 quintillion 3 months 24 years 24 centuries 237 centuries
13 7.18 sextillion 11 years 11 centuries
14 345 sextillion 5 centuries 546 centuries
15 16.5 septillion 262 centuries
16 794 septillion
Crack Time – Fake Word Passwords
Recombined syllables in the common words Average time to crack based on number of guesses per second
Size Possible combinations 1 trillion (expected future capability) 100 billion (large distributed system) 1 billion (distributed system or supercomputer) 100 million (small distributed system) 1 million (single computer)
3 22.2 billion instant instant 11 seconds 2 minutes 3 hours
4 7.66 trillion instant 38 seconds 1 hour 11 hours 1 month
5 2.65 quadrillion 2 minutes 4 hours 15 days 5 months 42 years
6 914 quadrillion 13 hours 2 months 14 years 1 century 145 centuries
7 316 quintillion 6 months 50 years 50 centuries 501 centuries
8 109 sextillion 2 centuries 173 centuries
9 37.7 septillion 597 centuries
10 13 octillion
Crack Time – Common Word Passwords
9806 possible words Average time to crack based on number of guesses per second
Size Possible combinations 1 trillion (expected future capability) 100 billion (large distributed system) 1 billion (distributed system or supercomputer) 100 million (small distributed system) 1 million (single computer)
2 96.2 million instant instant instant instant 48 seconds
3 943 billion instant 5 seconds 8 minutes 1 hour 5 days
4 9.25 quadrillion 8 minutes 13 hours 2 months 1 year 1 century
5 90.7 quintillion 2 months 14 years 14 centuries 144 centuries
6 889 sextillion 14 centuries
7 8.72 octillion

Magic Password Length

There is no magic length when it comes to creating a strong password because if everyone used the same length then it would be easier for hackers to guess your password, since they would not need to test combinations in the lower password lengths therefor greatly decreasing the time spent guessing your password. You should also be aware that you should not trust password strength meters as a sole factor when creating a strong password.

Personally, when using a long password I avoid using a password that uses an equal number, statistically people tend to use equal numbers, factor of 2, e.g. 6, 8, 10, 18, 20 etc. While a password at the length of 20 characters is technically stronger than a password length of 19, it doesn’t always necessary mean the time to crack will be less as the hacker may first target equal numbers.

I recommend using a large password around 20-30 or more using random strings, obviously you would need to use some kind of secure system to store the password, such as Roboform combined with Multifactor Authentication, or if your super gifted with a good memory then you could just remember a long writable password.

Password strength and possibilities of it being hacked is an interesting topic and I highly recommend that if security is the upmost importance to you or your company, then it’s worthwhile doing some further research on the topic.

WP Brute Force Prevention Methods

There are lots of ways on how you can prevent people and bots brute forcing their way into your WordPress website. Below are just a few ways that you can prevent unauthorised access via password cracking:

= Recommended


Brute Force Prevention against xmlrpc.php

XML-RPC has been enabled as default since WP version 3.5, with XML-RPC support enabled you can post to your WordPress blog using many popular 3rd party Weblog Clients,. Sadly, this is another entry point for hackers to gain access to your website. If you’re not using a remote publishing client then I highly recommend that you block all access to this file.

Here’s a few ways that you can prevent people using xmlrpc.php against you:

Renaming xmlrpc.php
mv xmlrpc.php randomstring.php
Deleting xmlrpc.php
rm xmlrpc.php
.htaccess Deny
<FilesMatch "xmlrpc.php">
	Order Deny,Allow
    deny from all
</FilesMatch>

You should be aware that if you decide to delete or rename xmlrpc.php then you should expect to see lots of 404 errors in your access logs.


WP Brute Force plugins

brute force wordpress plugins

Many WP plugins will stop brute force hackers in their tracks however because most plugins work on banning IP addresses after X attempts they may not stop determined password crackers using multiple IP blocks in the thousands.

Most plugins lift bans after X minutes meaning with enough IP addresses you become pretty much immune to these bans unless you opt to use an extremely long duration on those bans. Administrators generally do not use long duration bans because they don’t want to get locked out themselves.

Determined hackers with access to thousands of IP addresses will likely overcome these plugins, it’s just a matter of time, the more complex your username and password is the longer it will take them, even if they don’t get in they are using up your server-side resources and one of the reasons I highly recommend that people opt to use a .htaccess or fail2ban solution.


Deny Access to No Referrer Requests

deny referrer

Similar to the method of combating comment spam you can opt to use a referrer method which basically means the bot would need to submit the username and password from the actual page hosting the contact form.

You can use this method by adding the following code to your .htaccess file, obviously change example.com to the name of your domain.

Apache
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} POST
    RewriteCond %{REQUEST_URI} .(wp-comments-post|wp-login)\.php*
    RewriteCond %{HTTP_REFERER} !.*example.com.* [OR]
    RewriteCond %{HTTP_USER_AGENT} ^$
    RewriteRule (.*) http://%{REMOTE_ADDR}/$1 [R=301,L]
</ifModule>
Nginx
location ~* (wp-comments-posts|wp-login)\.php$ {
        if ($http_referer !~ ^(http://example.com) ) {
          return 405;
        }
      }

ModSecurity

modsecurity shield logo

You can use ModSecurity which is a security module for Apache, some shared hosting accounts do not allow it, or they do but it may be limited somewhat. If you have a vps, dedicated or shared hosting account that supports mod_security then you can use the following code:

SecAction phase:1,nolog,pass,initcol:ip=%{REMOTE_ADDR},initcol:user=%{REMOTE_ADDR},id:4900000
<Locationmatch "/wp-login.php">
        SecRule user:bf_block "@gt 0" "deny,status:401,log,severity:'2',id:4900001,msg:'IP has been blocked for 5 minutes, for attempting more than 15 login attempts in less than 3 minutes'"
        SecRule RESPONSE_STATUS "^302" "phase:5,t:none,nolog,pass,setvar:ip.bf_counter=0,id:5000136"
        SecRule RESPONSE_STATUS "^200" "phase:5,chain,t:none,nolog,pass,setvar:ip.bf_counter=+1,deprecatevar:ip.bf_counter=1/180,id:5000137"
        SecRule ip:bf_counter "@gt 15" "t:none,setvar:user.bf_block=1,expirevar:user.bf_block=300,setvar:ip.bf_counter=0"
</Locationmatch>

But note the above code does not stop hackers that use IP rotation methods to avoid being banned.


Fail2ban

fail2ban flat logo

I’m a huge fan of Fail2ban and I use it on all my virtual private servers, but sadly most shared hosts do not run it, nor will they allow you to install it. Since fail2ban has many features shared hosting companies will most likely already be making use of it, but they will not have it configured to combat brute force attacks on WordPress, however some do.

Some hosting companies may set it up for you if you ask nicely, after all… it’s in their best interest as saving server-side resources is an important aspect of running a host company. Brute force attacks can consume a lot of server side resources if their server doesn’t throttle, or ban them.

If you have a virtual private server (vps) or dedicated server then installing fail2ban for WordPress is pretty straight forward, below you can view an easy to follow video tutorial on the subject.


Blocklists

ip blocklists

Blocklists AKA IP blacklists can be used to pre-ban IP addresses that are up to no good, however this method depends on the fact that these are already in the database, obviously hackers who use rotating IP blocks and get issued new IP blocks regularly will not be on these databases.

In my honest opinion this method is a complete waste of time in blocking brute force attacks, therefor I’m not even going to mention how you can go about using this method, just don’t do it!


Cloud Services

cloudflare prevent brute force attacks

Cloud services that act as a transparent proxy will often block various attacks such as DOS attacks and Brute Force attacks. Such services come to mind are Cloudflare which basically sits in front of your website that will take a significant portion of web requests and they have the opportunity to, literally, patch Internet vulnerabilities in real-time.

Not all requests are sent through the service but it will greatly increase the time to hack a site, an easy solution with many site speed benefits. Highly recommended for most novice users.


IP Limited Access to wp-login.php

ip deny

Generally most shared hosting platforms use an Apache platform so the best way to harden your WordPress login is to use the Apache Deny Directive which works by denying all IP addresses other than the ones that you allow. This is great for setting access permissions to either the file wp-login.php or the entire wp-admin folder.

Not only is this the best method for shared hosting but in fact it’s great for all VPS and dedicated servers, if you prefer not to use fail2ban. You can deny all IP addresses and then only allows yours, this works great for users that have an static IP, however not so great for users that have a dynamic IP, which in fact most broadband users in the UK have, but don’t worry there’s a solution for you too!

If you have a dynamic IP then you can use the host method which basically means only people using your ISP can login, obviously this isn’t as secure as setting a static IP but 99.9999999% of attempts to crack your passwords won’t come from your ISP because they do not want to get in trouble with their ISP, or the local authorities, as hacking a website is illegal.

So, let’s take a look how you can harden your WordPress login against brute attacks using the htaccess.

Static IP Address

<FilesMatch "wp-login.php">
	Order Deny,Allow
    deny from all
    allow from 8.8.8.8
</FilesMatch>

You will need to obviously change 8.8.8.8 to match your own IP address.

Static Multiple IP Addresses

<FilesMatch "wp-login.php">
	Order Deny,Allow
    deny from all
    allow from 12.8.231.8
    allow from 93.1.1.12
    allow from 80.1.1.92
</FilesMatch>

Subnet IP Addresses

<FilesMatch "wp-login.php">
	Order Deny,Allow
    deny from all
    allow from 12.8.231
    allow from 93.1.1
    allow from 80.1.1
</FilesMatch>

Dynamic IP Addresses (hostname)

<FilesMatch "wp-login.php">
	Order Deny,Allow
    deny from all
    allow from .isp.example.com
</FilesMatch>

You will need to obviously change .isp.example.com to match the same hostname that your office or home broadband hostname uses. You can do this by finding out your external IP address then doing a do a reverse IP lookup.


IP Limited Access to /wp-admin/

ip deny

Generally blocking wp-login.php is more than sufficient but if your super paranoid you can block the entire WordPress admin folder by creating a .htaccess in the /wp-admin/ folder.

Your .htaccess file within /wp-admin/ should look something like this:


	Order Deny,Allow
    deny from all
    allow from 63.8.231.8
    allow from 63.12.2.12
    allow from 80.100.11.92

Static IP Address

Order Deny,Allow
    deny from all
    allow from 4.4.4.2

You will need to obviously change 4.4.4.2 to match your own IP address.

Static Multiple IP Addresses

Order Deny,Allow
    deny from all
    allow from 23.8.131.18
    allow from 24.10.1.12
    allow from 80.11.221.192

Subnet IP Addresses

Order Deny,Allow
    deny from all
    allow from 116.4.233
    allow from 195.15.1
    allow from 182.5.4

Dynamic IP Addresses (hostname)

Order Deny,Allow
    deny from all
    allow from .isp.example.com

You will need to obviously change .isp.example.com to match the same hostname that your office or home broadband hostname uses. You can do this by finding out your external IP address then doing a do a reverse IP lookup.


Protect Using htpasswd wp-login.php

htpasswd

You can add an extra lever of security by using htpasswd, this will give you two login prompts rather than one. The first password prompt will be by the server daemon and then the later WordPress. It should be noted that if your server does not use SSL then your username and password credentials can be stolen. If your website does not use SSL then I highly recommend that you use the DENY all by IP method.

Simply add this to your current .htaccess file:

Apache 2
<Files wp-login.php>
AuthUserFile ~/.htpasswd
AuthName "Private access"
AuthType Basic
require user mysecretuser
</Files>
Nginx
location /wp-login.php {
    auth_basic "Administrator Login";
    auth_basic_user_file .htpasswd;
}

You will need to create a htpasswd file using cPanel, Plesk, SSH or various other online apps.


Protect Using htpasswd /wp-admin/

htpasswd

Generally blocking wp-login.php is more than sufficient but if your super concerned about security then you can use this method, just take note that if your site is not SSL enabled or enforced then people can packet sniff your username and passwords.

Simply create a .htaccess file in the root of /wp-admin/ with the following contents:

AuthUserFile ~/.htpasswd
AuthName "Private access"
AuthType Basic
require user mysecretuser

You will need to create a htpasswd file using cPanel, Plesk, SSH or various other online apps.


Need some Help?… then leave a comment!

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

15 Responses to “10+ Ways to Stop WordPress Brute Force Attacks”

  1. Really nice write up Simon, liked the fact that you covered complex passwords… So many people use their DOB for their passwords and they wonder why they get hacked!

    Reply
  2. The complex passwords covered by Stephen Ostermiller is actually rather interesting, some passwords that I would consider weaker than longer passwords are the opposite. I think the faster computers are getting the more at risk people are of being hacked. Soon, computers will be able to crack passwords in realtime and the need for server-side protection against brute attacks will be higher than ever! Great read, thanks!

    Reply
  3. thu thuat

    Best article, I’ll follow and increase my site security.

    Thanks

    Reply
  4. Donald Piccione

    Hi Simon, excellent article.

    Recently, after hiding wp-admin login page, I still have brute force attack to pages that do not exist, generating 404.
    IP’s are generated by proxy I suppose, as have every time different location.
    I also use CloudFlare but doesn’t help with this.
    Any idea how to avoid inexistent pages to be pinged by this hacking bots? Best, Donald

    Reply
    • Hi Donald,

      I’d consider Fail2Ban… it can block repeat offenders like the ones you are experiencing.

      Reply
      • Did you give BruteGuard a try? It’s a free cloud powered WordPress Plugin which helps you to protect your site in the most efficient way as it syncs all attacks network wide and therefore can protect your site before an attack is even happening.

        Reply
  5. vitaljik

    Hi! I wanted to use Deny Access to No Referrer Requests, but I don’t really understand where to use that Nginx code? Could you please guide me? I am new to NGINX. Thanks!

    Reply
  6. leslie

    Very informative article. I am installing the auto internal link creator plugin, but after installing, it is generating lots of unwanted external links from my webpages on some nonsense word. Is it brute force attacks or else? otherwise I will delete that plugin but still do not know how to solve this issue instead of going manual to every post?

    Reply
  7. مستروب

    Very nice article, thanks.

    Reply
  8. Thanks, I’ll give it a go.

    Reply
  9. Hi, thank you for this useful article.

    I have 1 question: How is possible that “Fake Word Passwords” is the most secure system to create passwords?

    If you think a “fake words” can be 1 specific combination a of a “Random Passwords”, so how this is possible?

    Reply
    • Hi Good, question. I will ask the author Steve, but I think it might be because size = words, not characters… But give me a few days and hopefully I’ll have some answers for you!

      Reply
  10. Hi, I was thinking about renaming xmlrpc as I noticed thousands of access every month, but I’m also concerned about bandwidth wasted by bots as my 404 page is several KB bigger than the real xmlrpc file. What do you think if I rename xmlrpc and then create a new xmlrpc.php file that is just 1 byte in size with just like a 0 inside to reduce bandwidth waste when bots call it? Could this create new security problems or it may work? Thanks

    Reply
    • Hi Fabio, renaming XMLRPC will indeed result in 404 errors, but it should be noted 404 errors is the correct error to return for something that doesn’t exist. You should consider using Cloudflare if you are concerned with bandwidth since this will prevent bots and people hammering the same URL over and over again, as it will treat those as attempted hacks and because Cloudflare sits between your server and the user, it stops server-side requests.

      Reply
  11. Great post that will help me strengthen my WordPress install, thanks.

    Reply