If your WordPress site hosts malicious files, redirects your visitors, or sends spam, it has likely been compromised. This article describes the procedure to follow, in order, via the command line using WP-CLI through your SSH access.
The order of the steps matters. Updating WordPress before assessing the damage erases traces of the intrusion without removing the backdoor. Follow the steps in the indicated order.
| # |
Step |
Objective |
| 1 |
Recognize the compromise |
Confirm that it is indeed a hack |
| 2 |
Preserve the current state |
Save evidence, take the site offline |
| 3 |
Assess the extent |
Know what has been modified |
| 4 |
Clean up |
Restore files, purge the database |
| 5 |
Regain access |
Cut the attacker off from the site |
| 6 |
Update |
Close the entry vulnerability |
| 7 |
Harden |
Prevent recurrence |
In short: back up the site as it is and take it offline, assess the damage (wp core verify-checksums), restore the core with wp core download --force, regain access (wp config shuffle-salts), and only then update.
1. How do I recognize a compromise?
- Unexpected redirects, injected pages, or content that only appears for visitors coming from a search engine
- Traffic spikes on URLs you do not recognize
- Malicious files flagged by your host or by your browser
- Administrator accounts you did not create
- Sending spam from the domain, or the domain being placed on a blacklist
2. Before anything else: preserve the current state
- Back up the site as it is, files and database, even if infected. This is your only copy of the evidence, and your safety net if the cleanup breaks something. From the Apanel console, a downloadable archive gathers the files and databases into a single file: see Back up or export your site as a downloadable archive.
- Do not launch any updates for now (see the warning above).
- Make the site unavailable during the intervention, so it no longer serves malicious content to your visitors. If your server offers it, prefer the Site maintenance of the Apanel console (Hosting management > Website card > Site maintenance): the unavailability page is served without going through the WordPress code, which the attacker may have modified. Otherwise, use WP-CLI:
wp maintenance-mode activate
3. How do I assess the extent of the damage?
Connect via SSH to your account, then navigate to the site directory.
WordPress core files
wp core verify-checksums
Compares your installation against the official files. Any modified, added, or missing file is reported.
Plugins
wp plugin verify-checksums --all
Limited scope. This check relies on checksums published by WordPress.org. Premium, custom, or manually installed plugins cannot be verified this way: check them manually or reinstall them from their original source. Themes do not have an equivalent verification.
PHP files where they should not be
The uploads folder should only contain media. A PHP file found there is a strong signal:
find wp-content/uploads -type f -name "*.php"
Also identify recently modified files, keeping in mind that an intrusion may be old:
find . -type f -name "*.php" -mtime -30
Classic persistence locations
A backdoor often survives a superficial cleanup by hiding here:
| Location |
Why it is a sensitive point |
wp-content/mu-plugins/ |
Plugins loaded automatically, invisible in the plugin list |
wp-content/object-cache.php advanced-cache.php db.php |
"Drop-in" files, loaded very early by WordPress |
wp-config.php .htaccess |
Code or redirection rules added at the end of the file |
Accounts and scheduled tasks
wp user list --role=administrator
wp cron event list
An unknown administrator account, or a scheduled task whose name does not correspond to any installed plugin, are serious clues.
4. Clean up
Restore the WordPress core
wp core download --force
Do not use wp core update for this. If your site is already on the latest version, wp core update considers there is nothing to do and leaves the files modified by the attacker in place. Only wp core download --force rewrites existing files in all cases. This command does not touch wp-content, wp-config.php, or your database.
Plugins and themes
- Delete everything that is not used: an inactive theme or plugin remains executable
- Reinstall from the official source any items flagged as modified
- Delete any plugin that is no longer maintained by its author
Database
Search for the most common injections:
wp db search "<script" --all-tables
wp db search "base64_decode" --all-tables
Do not confuse. wp db check and wp db repair check the technical integrity of MySQL tables. They neither detect nor remove any malicious content and have no place in a hack cleanup.
5. How do I regain control of access?
As long as this step is not completed, the attacker can return with the credentials or session they already possess.
wp user delete <ID> --reassign=<ID_d_un_compte_légitime>
wp user reset-password <utilisateur> --show-password
Then invalidate all open sessions by regenerating the security keys, the most often forgotten step:
wp config shuffle-salts
All users, including the attacker, are immediately logged out.
Do not forget access outside WordPress: your Apanel console password, FTP/SFTP and SSH access, and database user (to be reflected in wp-config.php).
6. Update, only now
The assessment is done and access has been regained: updates can be applied.
wp core update
wp plugin update --all
wp theme update --all
7. Reduce the risk of recurrence
wp config set DISALLOW_FILE_EDIT true --raw
wp config set FORCE_SSL_ADMIN true --raw
The first command disables the file editor in the administration, which allows a compromised account to modify code without server access. The second forces administration over HTTPS.
Complete this with:
- Two-factor authentication on administrator accounts
- Limiting login attempts
- A recognized security plugin, or a web application firewall (WAF)
- Regular updates: the vast majority of compromises exploit a vulnerability fixed months ago
Then bring the site back online: turn off Site maintenance in the Apanel console, or, if you used WP-CLI:
wp maintenance-mode deactivate
When should I seek help?
A successful cleanup leaves no modified files upon the second check. If wp core verify-checksums continues to report files, if injections reappear, or if you are not comfortable with these manipulations, do not leave the site in production: open a request with our support specifying what you have already tried.
See also: Manage a WordPress site from the command line (WP-CLI).
Going further