Blocking bot login attacks on WordPress

The Problem

If you run a self-hosted WordPress blog then you might – or might not! – be aware of the sheer volume of attempted logins that will be sent your way. A good way to monitor and cut down on this is the Limit Login Attempts Reloaded plugin, which logs and graphs them:

Graph showing >70 failed login attempts in one day

.. and which provides some tools to block login after X attempts, and to block/allow list IP addresses.

After a while, though, I found that even those tools weren’t enough; rather than making the existing security tighter I decided that the simplest solution was to add an extra layer of security in the form of a small plugin of my own.

The result can be seen in the graph above, which is for this blog – on July 8th I disabled my plugin as a test, by July 10th the bots clearly had it marked as a target and received almost 80 bot login attempts before I re-enabled the plugin again that evening.

Login Locker

The basis of my solution is that to block bot logins you don’t actually need to harden – or mess with – the existing WordPress login functions. In fact, maybe it’s better not to. All you need to do is make a change that will be simple for human users to accommodate, but which will confound an automated attack. And the simplest I’ve found is to modify the /wp-login.php path.

My little plugin, Login Locker, checks every attempt to login and looks for a keyword appended to the URL. So a visit to:

.. is accepted, and everything executes as normal from there. But if someone accesses:

.. without the keyword, it returns an immediate error 401.

So to use the site as usual, all humans have to do is bookmark a slightly modified login URL. From there they can login (the keyword is automatically passed by the login form), edit and then logout (the keyword is automatically appended to the logout URL) as usual. But a script on some remote server automatically hitting thousands of WordPress installs a day will get an error, shrug, and move on without ever meeting the real login interface.

The keyword to use in the URL – which is importantly not a password, as it will be inserted into pages in plain text – is configurable from a new menu item in /wp-admin/. If no keyword is set, login will function as normal.

I’ve been running this system for months and it has reduced the admin headache of managing WordPress considerably. If you’d like to give it a try, I’ve dropped the plugin code – it’s short and simple – on Github, here.