Module 7 · 7.3
English
Logging in: passwords, two-factor authentication and brute force
Module 7: Security · Reading time: 9 minutes
Learning objective: After this lesson you'll be able to lock down your website's login with strong passwords, two-factor authentication and limiting login attempts, and you'll know what xmlrpc.php is.
Key concepts: password manager, passphrase, unique password, two-factor authentication (2FA, TOTP), passkey, brute force, limiting login attempts, wp-login.php by IP address, xmlrpc.php, leaked usernames (REST, ?author=), application passwords
The password: long and unique
A good password has two properties:
- Long: length matters more than odd characters. A passphrase of four or five random words (
sieve-penguin-october-lantern) is stronger and easier to remember thanP4ssw0rd!. Security guidance commonly recommends a unique password of at least 12 characters, preferably a passphrase. - Unique: not used anywhere else. Credential stuffing (lesson 7.1) only works if you reuse a password.
Nobody remembers dozens of long, unique passwords. That's why you should use a password manager: a program that creates, stores and fills them in for you. Then you only need to remember one: the manager's own password, and you should secure that with two-factor authentication too.
You can check whether a password appears in a known data breach at haveibeenpwned.com. If your email address shows up in a breach, change the password for every service where you used that same password.
Two-factor authentication
With two-factor authentication (2FA), you need something in addition to your password when logging in: usually a six-digit code from an app on your phone (an authenticator, following the TOTP standard). An intruder with your password still can't get in.
WordPress doesn't have built-in two-factor authentication. You add it with a plugin. There are many; a simple one is Two Factor, made by contributors to WordPress itself. Security plugins often include it too. When choosing one, look for:
- TOTP apps and backup codes (in case you lose your phone); codes by email are weaker, because your mailbox can be hacked too;
- the ability to require it for administrators and editors;
- passkeys: logging in with your fingerprint, face or a security key, without a password. There are plugins for this too. Passkeys resist phishing, because they only work on the genuine website.
Turn on two-factor authentication on everything around your website as well: your hosting panel, your email, your registrar and your password manager. An intruder who takes over your hosting panel doesn't need your WordPress password.
Brute force and limiting login attempts
An open WordPress website gets login attempts on wp-login.php all day long, often with admin and lists of commonly used passwords. With a long password and 2FA they won't get in, but every attempt costs your server processing time (a full WordPress start). During a large wave, your website slows down.
WordPress itself doesn't limit the number of attempts. What helps, in order of "stopping it early":
- On the server: many hosts block an IP address that makes many failed attempts in a short time, before WordPress even starts (with a firewall or a web server feature). Ask your host what happens.
- wp-login.php restricted to your IP address: with a few lines in
.htaccess(with LiteSpeed and Apache):
<Files wp-login.php>
Require ip 192.0.2.10
</Files>This works well if you have a fixed IP address. If you don't (at home, on your phone), you'll lock yourself out when your address changes. An alternative is an extra password on the login page (a "protected directory", basic authentication) with a password different from your WordPress password.
- A plugin that limits attempts: after five failed attempts, the IP address is blocked for a while. It works, but only once WordPress is already running, so the processing cost remains.
Hiding or renaming the login page (for example /my-login instead of /wp-login.php) reduces the noise in your log. It isn't real security, and some plugins and themes expect the default address. Fine as an extra, never instead of a good password and 2FA.
xmlrpc.php
xmlrpc.php is an old interface from before the REST API, through which apps and other websites talk to WordPress. It's still used by some apps, by Jetpack and by a few integrations. For most websites it's unnecessary.
Intruders love xmlrpc.php, because you can try hundreds of passwords in a single request (with the system.multicall function), and because it can be abused to attack other websites (pingbacks). What to do:
- You don't use it: block it. Some hosts, including WebOké, block xmlrpc.php on the server by default. Otherwise, with a rule in
.htaccessor with a security plugin. - You do use it (for example for an app that needs it): leave it open, but make sure you have strong passwords, 2FA and a limit on attempts. Modern apps usually use the REST API with an application password (lesson 3.3).
Leaked usernames
In lesson 3.3 you saw that WordPress exposes a derivative of usernames:
https://example.com/?author=1redirects to/author/<name>/;https://example.com/wp-json/wp/v2/usersshows a list of the slugs of everyone who has published something.
Is that bad? A username isn't a password. With a long unique password and 2FA, it makes little difference. But it gives an intruder half of the login details and makes targeted phishing easier. Reasonable measures:
- give administrators a username that isn't their public name, and don't publish with an administrator account (lesson 3.3);
- restrict the user list in the REST API with a security plugin or a few lines of code, if you don't need it. Don't close the REST API completely: the block editor and many plugins need it.
Application passwords
Application passwords (lesson 3.3) are a safe way to give an app or system access, but they bypass your two-factor authentication: an app with an application password doesn't need a code. Only create them when needed, on an account with a low role, and revoke them when you stop using the integration.
Summary
- Use long, unique passwords (passphrases) in a password manager.
- Turn on two-factor authentication, with a plugin in WordPress and also on your hosting panel, email and registrar.
- Stop login attempts as early as possible: on the server, with an IP rule or extra password, or with a plugin.
- Block xmlrpc.php if you don't use it.
- Leaked usernames aren't a disaster, but they are a hint: don't publish as an administrator and restrict the REST user list if you don't need it.
Quiz
Exercise
Exercise A7.3: What does your website reveal when logging in? Enter your website's address and prove that it's your own website (with the exercise's code, as a TXT record or as a file). The programme checks three things: whether xmlrpc.php returns a list of functions (open) or is blocked, whether /wp-json/wp/v2/users shows usernames (slugs), and where /?author=1 redirects to. Indicate whether you need xmlrpc.php; if not, an open xmlrpc.php shows red. Leaked slugs show orange with an explanation.
Exercise D7.3: Turning on two-factor authentication. Turn on two-factor authentication for all administrators of your WordPress website, and also on your hosting panel and your email. Store the backup codes in your password manager. Tick off each part once it's turned on and note which method you use (app, passkey, email) and where the backup codes are stored. Also note how you additionally protect wp-login.php and why you chose that method.
Exercise D7.3: Turning on two-factor authentication
You do this exercise yourself; no one checks it. Tick off what you've done and mark the exercise as done.
For administrators, prefer an app or passkey over email alone. If you have a fixed IP address, you can allow that on wp-login.php; with changing addresses, limiting login attempts works better.
Your ticks and notes only stay in this browser; we don't send them anywhere. If you're signed in, we only save in My courses that you've done the exercise.
Further reading
These articles describe the steps in WebOké's panels; in other panels they work similarly.
- DirectAdmin guide 3.7: Secure passwords and what to do if a password is leaked
- Two-step verification in My WebOké and setting up an authenticator app
- WordPress xmlrpc.php access not working
- Securing wp-login.php in WordPress
- DirectAdmin guide 15.9: Password Protected Directories
- Logging in securely (developer.wordpress.org, English): https://developer.wordpress.org/advanced-administration/security/brute-force/
- Brute force attacks (developer.wordpress.org): https://developer.wordpress.org/advanced-administration/security/brute-force/
