Blog · What the free audit finds
Login Names Are Half a Login
Ask a WordPress site for its list of users and, by default, it answers. Every author's login name, in a machine-readable list, at a fixed address. Attackers do not have to guess who the accounts are. They only have to guess the passwords.
Where the list comes from, how the free audit reports it, and the four changes that close it without locking anyone out.
Where the list comes from
WordPress carries a programming interface that other software uses to read the site: the mobile app, the block editor, integrations. One part of it lists users. By default anyone can read it, logged in or not, at the site's address followed by /wp-json/wp/v2/users. The list shows each account's public name and its login slug, which on most sites is the login name itself.
There is an older route to the same information. Asking for the site's address followed by /?author=1 redirects to the first account's archive page, whose address contains the login name. Counting up from one walks the whole staff.
Why a username matters
A login has two halves. Guessing both is slow. Guessing one, with the other handed over, is a matter of trying passwords, and password lists from other breaches are cheap. A site whose usernames are public is a site where every account's security rests on its password alone.
The legacy remote interface, xmlrpc.php, makes the guessing faster still. One request can carry hundreds of password attempts. It is enabled by default, and most sites have not used it since the WordPress mobile app stopped needing it.
Four changes
First, restrict the user list to logged-in visitors. Security plugins offer the setting, and it is a short filter for a developer to add. The block editor and the app still work, because they are logged in.
Second, turn off xmlrpc.php unless a specific integration needs it. Jetpack and a few older mobile tools do; if your site uses one of them, keep it on and put a rate limit in front of it instead.
Third, give every account that can publish a second factor. This is the change that matters most, because it makes a guessed password useless. An authenticator app on a phone is enough. Administrators first, then editors, then everyone.
Fourth, rename or remove the account called admin, and make the display name of each account different from its login name. Neither is a defense on its own. Both remove the easiest guess.
What not to bother with
Moving the login page to a secret address is popular and does little. The interface that lists users is a different door. A plugin that hides the WordPress version number does nothing for this either. Spend the time on the second factor.
What the free audit reports
The free audit asks the user list the same way an attacker would and reports how many login names came back, with the first few shown so you can recognize them. It also reports whether xmlrpc.php is answering. Both findings are moderate on their own and serious together, which is how they usually arrive.