Hardening WordPress logins: what to fix first, and where the login URL actually belongs
If you inherit a WordPress site, the login URL is often already renamed and the administrator list is often still untouched. The rename takes five minutes and looks like progress in a screenshot. Auditing who can install a plugin takes an afternoon and produces nothing you can show anyone. That order is backwards. Below is a sequence that holds up, and where the login URL actually fits.…
When you take over a WordPress site, the first step to securing the login process is to rename the login URL. This simple action takes only five minutes and can make a significant difference in your site's security. Simultaneously, audit the administrator list to identify any accounts with excessive privileges. Use the command `wp user list --role = administrator --fields = ID,user_login,user_email,user_registered` to list all administrators, and then loop through the users with the command `wp eval 'foreach ( get_users() as $u ) { if ( user_can( $u, manage_options ) ) { echo $u- user_login . \n ; }'` to find any accounts with the `manage_options` capability.
This is important because compromised administrators can install plugins that could compromise your site.
Next, move anyone with the ability to write content but not administer down to the editor role. Editors cannot install plugins or switch themes, significantly reducing their potential impact if their account is compromised. If there are accounts that belong to nobody, delete them and reassign their content to the correct users. This can be done using the command `wp user delete id --reassign= other_id`, which deletes the account and reassigns the user's content to another specified user.
In addition to these steps, check for application passwords and XML-RPC on accounts that should not have them. Application passwords are a separate credential that never touches your login form and can be disabled by adding a filter in your theme's `functions.php` file as shown in the source. XML-RPC can also be disabled using a similar filter, as shown in the source.
These steps are crucial because they limit the damage if a password is leaked. However, they do not protect against other methods of attack, such as application passwords, XML-RPC, or custom endpoints.
After securing the login process, focus on reducing the chance of a password leak. Enable two-factor authentication on the login form, which protects interactive browser logins. However, note that it does not protect application passwords, XML-RPC, or any custom endpoints that check passwords directly. Implement your chosen two-factor authentication method, such as TOTP with recovery codes printed and stored offline, and ensure that someone with WP-CLI access can reset enrollment in case of a lost phone.
To further enhance security, throttle login attempts at both the nginx level and application level. At the nginx level, use a rate limit in the http block applied to the login location. At the application level, count failures per source and short-circuit before the password is checked. This can be done using a custom plugin that tracks failed login attempts and blocks access after a specified number of attempts. These measures help prevent online guessing attacks at scale.
Finally, address the question of the login URL. Renaming `wp-login.php` filters automated noise out of your logs, which can be helpful but is not access control. A valid credential will still allow login, and XML-RPC and REST are untouched. Integrations that assume the default path may break due to the rewrite. Therefore, consider the login URL question after you have secured the login process.
If you decide to rename it, document the recovery path in handover notes, as the login URL can be changed without affecting the user's ability to log in.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.