Of all backdoors, an administrator user created by the attack is the simplest and the most resilient: it contains no code, scanners don’t flag it, and it survives any restore of the original files. A single login is enough to take control of the site again, reinstall malicious plugins and start over.
How they hide
A ghost administrator is rarely called “hacker.” It usually has a plausible name, like admin2, wpsupport or the name of a collaborator, and an email address similar to the owner’s. The more polished variants hide completely from the Users screen with a few lines of PHP, for example a filter on pre_user_query that excludes the user from the query, and they also correct the administrator count shown at the top of the page.
The key point is that these filters act inside WordPress. Everything that goes through WordPress, including the Users screen, sees the list already filtered.
Checking from the database and with WP-CLI
The reliable check is the one that doesn’t go through plugins and the theme. With WP-CLI you can exclude both from loading:
wp user list --role=administrator --skip-plugins --skip-themes \
--fields=ID,user_login,user_email,user_registered
Or you can query the database directly, remembering that the table prefix may differ from wp_:
SELECT u.ID, u.user_login, u.user_email, u.user_registered
FROM wp_users u
JOIN wp_usermeta m ON m.user_id = u.ID
WHERE m.meta_key = 'wp_capabilities'
AND m.meta_value LIKE '%administrator%';
If the results differ from what the Users screen shows, some code is hiding someone, and that code has to be found and removed just like the user.
Not just administrators
An attack doesn’t always need the administrator role. It’s also worth checking:
- users with lesser roles but with capabilities added by hand, such as
edit_pluginsorunfiltered_html, visible in the serialized value ofwp_capabilities; - application passwords, introduced in WordPress 5.6, which allow using the REST API without the main password: list them with
wp user application-password list <user>; - legitimate but no longer used accounts, such as those of former collaborators or agencies, which are often the original way in.
Removing without losing content
Before deleting a suspicious user, note down its details, because the registration date and email address help place the attack in time. Then delete it, reassigning any content to a legitimate user, and close all open sessions:
wp user delete 57 --reassign=1
wp user session destroy --all
wp config shuffle-salts
Regenerating the keys and salts in wp-config.php invalidates all login cookies, including any the attack may have stolen. Finally, the passwords of all remaining administrators should be changed and two-factor authentication enabled.
A ghost administrator is almost always the symptom of something else: a vulnerability, a weak password, a database trigger that recreates it. Deleting it is necessary, but the cleanup is complete only when you’ve worked out where it came from.