2026年11月14日
2026年11月14日
Recover a Hacked WordPress Admin Account (WP-CLI and phpMyAdmin)
This article is a localized edition of the Japanese original. Read the Japanese original
When a WordPress administrator account is hijacked, the attacker may change the password or email address so you can't log in, or add unknown administrator users and malicious files. This article assumes you can reach the server via SSH, a file manager or phpMyAdmin, and walks through regaining access and closing the entry points the attacker left behind.
Work in the order below. Don't stop once you can log in again; it is important to continue through "closing the entry points" in the second half. Even after a password change, the attacker can get back in if they left another administrator user or malicious files behind.
- Save the current state
- Take the site offline temporarily
- Regain access
- Invalidate everyone's logins
- Remove rogue users, settings and files
- Change related passwords
- Add preventive measures and reopen the site
Run the WP-CLI commands below in the WordPress folder (where wp-config.php is).
Step 1: Save the current state
Before deleting or overwriting anything, save everything as it is now. You will use it later to investigate what was done, or if you delete a file you needed. Save it somewhere not reachable from the web (outside the public folder).
# Export the database
wp db export ~/incident-db.sql
# Archive the files (replace /var/www/example with your WordPress folder)
tar czf ~/incident-files.tar.gz -C /var/www example
If your hosting has no SSH, use the control panel's backup feature, download via FTP, and use "Export" in phpMyAdmin.
Step 2: Take the site offline temporarily
So the attacker can't keep working and visitors don't see malicious content while you investigate, make the site reachable only from your own IP address. On Apache (servers where .htaccess works), add the following to the top of the .htaccess in the WordPress root. Replace the IP address with your own.
# During the investigation, allow access only from your own IP address (remove when finished)
Require ip 203.0.113.10
WordPress's maintenance mode via the .maintenance file ends automatically 10 minutes after the file is created, so it is not suited to keeping the site closed during long work. Some hosting companies offer a feature in the control panel to stop serving the site or restrict access.
Step 3: Regain access
With WP-CLI
First, list the administrator users.
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
If the email address of your account was changed, restore it first. Then generate a new password and display it.
# Restore your email address (without sending the change notification)
wp user update 1 --user_email=you@example.com --skip-email
# Generate a new password and show it on screen (no email sent)
wp user reset-password 1 --skip-email --show-password
Replace 1 with your user ID. Log in with the displayed password, then change it to your own on the Profile screen.
With phpMyAdmin
If WP-CLI isn't available, run SQL in phpMyAdmin. Match the table name prefix (wp_) to the $table_prefix value in wp-config.php.
-- Set a temporary password for user ID 1
UPDATE wp_users SET user_pass = MD5('your-temporary-password') WHERE ID = 1;
-- To restore the email address as well
UPDATE wp_users SET user_email = 'you@example.com' WHERE ID = 1;
WordPress accepts a password stored as an MD5 value and re-saves it with the current hashing method when you log in. Don't leave it as MD5: change your password on the Profile screen right after logging in.
Step 4: Invalidate everyone’s logins
To end any logins still held in the attacker's browser, regenerate the authentication keys. Everyone, including you, is logged out.
wp config shuffle-salts
Without WP-CLI, replace the eight lines from AUTH_KEY to NONCE_SALT in wp-config.php with new values generated by the WordPress.org secret-key service.
Step 5: Remove rogue users, settings and files
Unknown users and application passwords
# List all users with their registration dates
wp user list --fields=ID,user_login,user_email,user_registered,roles
# Delete an unknown user (reassign their posts to user ID 1)
wp user delete 5 --reassign=1
# Check application passwords for each administrator
wp user application-password list 1
# Delete any you didn't create (--all deletes every one)
wp user application-password delete 1 --all
Application passwords can be used to log in to the REST API and similar interfaces separately from the normal password. If the attacker created one, they can keep operating the site remotely even after you change the password, so check every administrator. In the admin, you can check and revoke them in the "Application Passwords" section of each user's profile screen.
Settings that are often tampered with
# Whether anyone can register (0 means no)
wp option get users_can_register
# Role for new users (subscriber by default)
wp option get default_role
# Admin email address and site URLs
wp option get admin_email
wp option get siteurl
wp option get home
If users_can_register is 1 and default_role is administrator, anyone can register as an administrator. If you don't use registration, restore them with wp option update users_can_register 0 and wp option update default_role subscriber.
Modified files
# Check that core files match the official release (also reports files that shouldn't be in core folders)
wp core verify-checksums --include-root
# Check files of plugins distributed on WordPress.org
wp plugin verify-checksums --all
# Check auto-loaded plugins (mu-plugins) and drop-ins
wp plugin list --status=must-use
wp plugin list --status=dropin
# Find PHP files in the uploads folder (normally there are none)
find wp-content/uploads -name "*.php"
# Find PHP files changed in the last 14 days
find . -name "*.php" -mtime -14
If core files differ, overwrite core with the same version and language. With --skip-content, wp-content is not touched. The example below is for the Japanese edition; for the English edition, drop --locale=ja.
wp core download --version=$(wp core version) --locale=ja --skip-content --force
wp-config.php is not part of the release, so it is not overwritten. Check by eye that no unfamiliar code has been added to it (such as long lines containing eval( or base64_decode().
If plugins or themes differ, reinstall WordPress.org ones with wp plugin install plugin-slug --force, and delete any you don't use. Replace paid plugins and themes with files downloaded again from the vendor.
If the tampering is widespread, or you can't tell how far it goes, restoring a backup from before the compromise may be quicker. Even then, do steps 3 to 6 after restoring (the attacker may already have been in at the time of the backup).
Step 6: Change related passwords
Besides the WordPress administrator password, change anything the attacker may know.
- Passwords of other administrators and editors (
wp user reset-passwordemails them a reset link) - The hosting control panel, FTP/SFTP and SSH passwords or keys
- The database password (update
DB_PASSWORDinwp-config.phpto match) - The mailbox of the admin email address
Step 7: Add preventive measures and reopen the site
# Update WordPress core, plugins and themes
wp core update
wp plugin update --all
wp theme update --all
# Install a two-factor authentication plugin
wp plugin install two-factor --activate
# Install a plugin that limits login attempts
wp plugin install limit-login-attempts-reloaded --activate
- Delete unused plugins and themes instead of just deactivating them.
- Set
wp-config.phpso only the owner and the web server can read it (400 or 440 according to the official WordPress documentation). On some hosts, though, PHP runs in a way that makes it unreadable with these values, so check your hosting company's recommendation. - If the site is registered in Google Search Console, check the "Security issues" report and, if there is a warning, request a review after cleaning up.
Finally, remove the Require ip line you added to .htaccess in step 2 to reopen the site.
Protecting the login page is also covered in "How to restrict the WordPress login page (wp-login.php) by IP address" and "How to limit login attempts in WordPress".
Summary
- Before deleting anything, save the database and files outside the public folder
- Make the site reachable only from your IP address before you start
- Regain access with
wp user reset-passwordor SQL in phpMyAdmin, and end everyone's logins withwp config shuffle-salts - Check for unknown users, application passwords,
users_can_registeranddefault_role, mu-plugins and PHP files in the uploads folder - Overwrite core and plugins with official releases, and also change the server, database and email passwords
Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)