One of the perils of running on WordPress is that everyone knows where your login page is. I mean, this is true of any CMS that has a default login page. It makes your site susceptible to credential stuffing. There are a couple of ways to protect your login page. I’ll walk through what I tried and where I ended up.

Plugins

WordPress, like most modern content management systems, supports plugins that will obscure your login page. In essence, you rename the URL from within WordPress. I tried one called WPS Hide Login. It’s as good an example as any of the pros and cons of using a plugin.

I talked about adding WPS Hide Login as part of a bunch of things you should do to harden your site. Once you own a web site, even if you outsource the work to someone else, I think you have the obligation to do so.

First, the pros. Using a plugin can reduce the technical knowhow you need to accomplish a task. The best written plugins will make their behind-the-scenes activity invisible. And really, what you are doing is pretty straightforward.

WPS Hide Login changes the default login from /wp-login.php or /wp-admin to /login. You can then assign any path to make yours unique. I’d recommend it, since anyone who looks at the login page plugins will soon know what the new default is. You might change it from /login to /lgnme or something (don’t use that; I didn’t either).

I was able to obscure my login URL in a matter of minutes and I saw the attempted

Now some cons.

Redirects are funny things. And you can find that other changes you make to your site cause the redirects to loop. This will block you from getting into your site. Normally you can just remove or rename the plugin’s folder. Open up your file transfer (FTP) program or access your CPanel file manager and navigate down into your site’s wp-content/plugins folder.

WPS Hide Login inserted some items in the database as well, though. I recently found myself unable to login and renamed the folder. No dice. I ended up having to hunt down a bunch of references in the database that may or may not have lingered.

Plugin support matters. A number of other people had experienced similar problems. Their wasn’t always a response from the developer but you could find solutions they’d recommended, including:

  • looking through your database for the replacement url (eg., lgnme). Unfortunately, they pointed to the wrong table or, at least in my case, I ended up finding it in sitemeta and not in options.
  • refreshing your permalinks. One thing I did was to review my .htaccess file to make sure that the WordPress permalink code looked right.

In the end I think what fixed my problem was, once having removed all of the references to the plugin AND renaming the folder, purging my Cloudflare cache. One of the lessons I took away was this: a plugin can be a non-technical solution to a problem, but undoing it can require a lot of technical knowhow.

Block at the .htaccess file

I decided to go back to basics. This requires a bit of technical knowhow but not much. You can limit access to your login pages by IP address. The method relies on the .htaccess file.

I hadn’t been sure that I needed anything. At first, there didn’t seem to be any reason to worry. But within 24 hours of removing the plugin, my site was getting a login attempt every minute.

A screenshot from the JetPack application showing the activity log for this blog, and repeated attempts to login to the admin page as the user Admin.

WordPress creates this file when you create a site if it doesn’t already exist. It controls how people access files and folders on your web site. You can access it and edit it like a text file. Use your FTP program or (my preference) edit through your CPanel file manager.

I always make a copy before I start editing. I open up a NotePad file on my computer and paste the contents of the .htaccess file in. Then I can start adding code.

In this case, I added a <files> section. It works like any HTML tag. Make sure you close it with </files>. Here’s more detail but the code I put in looked like this:

# Login Limitation
<Files wp-login.php>
Order Deny,Allow
# Deny all access
Deny from all
# EXCEPT from the following IP addresses
Allow from nnn.nnn
</Files>

You can add this code to the bottom of the .htaccess file if you’re unsure where it goes. Just make sure it isn’t nested inside any other text. The lines that begin with # sign are comments. They can help you remember why you did something or what it does.

The only change you would make is to change the nnn.nnn part to actual IP addresses. If you’re always accessing your WordPress site from a corporate computer, this can be easy. Open up your web browser and type “what is my ip”? For my organization, every computer appears to come from the IP range starting with 142.57. So in my .htaccess file, I could change the Allow line to read:

# Login Limitation
<Files wp-login.php>
Order Deny,Allow
# Deny all access
Deny from all
# EXCEPT from the following IP addresses
Allow from 142.57
</Files>

Since my blog is personal, I need to do the same thing from my home. If you have a static IP address – one that doesn’t change – then this is just as easy as a corporate IP address. I don’t, though. My IP address changes every time my router and modem reconnect to the internet. This means that my file looks more like this:

# Login Limitation
<Files wp-login.php>
Order Deny,Allow
# Deny all access
Deny from all
# EXCEPT from the following IP addresses
Allow from 111.222
Allow from 333.444
Allow from 555.666
</Files>

This means that, potentially, other people who use my ISP could get to my login page. It’s a risk I’m willing to live with. If I start seeing automated attempts from someone using my ISP, I can deal with that separately.

As soon as I edited and saved the .htaccess file, I was back in business. I double-checked my web site to make sure it still loaded. If you have a typo in your .htaccess, it will stop the server from delivering your web site. Once I was sure it was working, I closed the CPanel editor and discarded the NotePad backup.

[Mon Sep 21 08:07:32.353926 2020] [access_compat:error] [pid 25663:tid 47843310286592] [client 185.86.164.103:61602] AH01797: client denied by server configuration
[Mon Sep 21 05:11:03.054818 2020] [access_compat:error] [pid 18479:tid 47843308185344] [client 125.64.94.213:56436] AH01797: client denied by server configuration
[Mon Sep 21 00:13:41.602272 2020] [access_compat:error] [pid 19217:tid 47843297679104] [client 185.86.164.98:49148] AH01797: client denied by server configuration
[Sun Sep 20 23:08:37.478465 2020] [access_compat:error] [pid 7117:tid 47843259856640] [client 185.86.164.102:27936] AH01797: client denied by server configuration
[Sun Sep 20 18:38:28.833380 2020] [access_compat:error] [pid 10293:tid 47843285071616] [client 185.86.164.107:55618] AH01797: client denied by server configuration
[Sun Sep 20 17:33:18.607921 2020] [access_compat:error] [pid 10900:tid 47843291375360] [client 185.86.164.109:48848] AH01797: client denied by server configuration
[Sun Sep 20 16:03:59.963456 2020] [access_compat:error] [pid 6129:tid 47843280869120] [client 185.86.164.99:23432] AH01797: client denied by server configuration
[Sun Sep 20 15:00:53.655758 2020] [access_compat:error] [pid 10829:tid 47843270362880] [client 185.86.164.100:62912] AH01797: client denied by server configuration
[Sun Sep 20 13:42:57.549825 2020] [access_compat:error] [pid 23452:tid 47843287172864] [client 185.86.164.102:25660] AH01797: client denied by server configuration
[Sun Sep 20 12:37:47.200864 2020] [access_compat:error] [pid 3488:tid 47843295577856] [client 185.86.164.106:43744] AH01797: client denied by server configuration
[Sun Sep 20 10:59:41.167066 2020] [access_compat:error] [pid 11961:tid 47843303982848] [client 86.153.11.156:37148] AH01797: client denied by server configuration
[Sun Sep 20 10:59:23.894421 2020] [access_compat:error] [pid 11421:tid 47843264059136] [client 66.249.79.88:16876] AH01797: client denied by server configuration

It’s been 24 hours and no more login attempts have been captured in JetPack. They are still attempting to access the site- I can see the errors in the log file, above – butthey are no longer able to reach the login page and attempt a username/password combination.