Skip to content

Cookie settings

Choose which kinds of cookies you allow. You can change your choice at any time via Cookie settings at the bottom of every page. Privacy statement

Necessary

Always on

Needed to log in, keep your cart and remember your choices. These are always on.

Which cookies?
  • weboke_sessie, weboke_klant, weboke_remember: your session and staying logged in
  • weboke_basket: your cart
  • wkBtwIncl: showing prices with or without VAT
  • wok_cookies: your cookie choice, 12 months

Measures which ad leads to a visit or order, so we do not pay for ads that do nothing.

Which cookies?
  • Google Ads via Google Tag Manager (_gcl_au, _gcl_aw), up to 90 days
  • OpenAI Ads, ads in ChatGPT
  • wok_aff: which partner referred you to us (affiliate programme), 60 days

4.6

Country and language

Each country has its own site, with prices and VAT for that country.

View

Module 7 · 7.3

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:

  1. 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 than P4ssw0rd!. Security guidance commonly recommends a unique password of at least 12 characters, preferably a passphrase.
  2. 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":

  1. 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.
  2. 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.

  1. 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 .htaccess or 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=1 redirects to /author/<name>/;
  • https://example.com/wp-json/wp/v2/users shows 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

1. Which password is the strongest?



2. Why is xmlrpc.php popular with intruders?



3. You restrict wp-login.php to your office's IP address. What's the risk?



4. Is renaming the login page to a secret address sufficient security?



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 A7.3: What does your website reveal when logging in?

This check requests paths that only get checked on your own website. First click "Show my code" and add that code as a TXT record on _weboke-cursus.<your domain> or as a file on your website (see the explanation next to the code).



What you enter and what we find isn't stored. Your browser remembers your answers and whether you've passed the exercise. If you're signed in, we only save that you got the exercise (almost) right in My courses; you can delete that there too.

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.




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.

One moment…

Set up your domains

For each domain, arrange the nameservers, the link to your hosting and who becomes the owner.

Loading your domains…