Hacked WordPress: the cleanup order that holds
Most hacked sites get cleaned twice. The first time removes what you can see. Here is the full order we use so the second time is never needed: contain, find the door, clean, rotate, patch, watch.
The sentence we hear most is “we cleaned it but it came back”. A cleanup that removes the visible damage and leaves the entry point open is a cleanup for a week. This is the order we work in, and why each step is there.
1. Contain
Before anything, stop the site doing more harm. Put it in maintenance mode or, if it is actively redirecting visitors or sending spam, take it offline for the hour. Take a full snapshot of files and database in this state. You will want to be able to look back at it.
Then log everyone out. In WordPress that means changing the secret keys in wp-config.php, the block of lines starting AUTH_KEY and SECURE_AUTH_KEY. Every session, including the attacker’s, ends at once.
2. Find the door
This is the step that gets skipped, and it is the whole job. Ways in, roughly in order of how often we see them:
- A plugin or theme with a published vulnerability, not updated. Check every version against the current release.
- An admin password reused from a service that leaked, or simply weak. Look at the users list for accounts you do not recognise and at the last login times.
- A second site on the same hosting account that was already compromised. Shared accounts share the filesystem.
- An old installation left in a subfolder, called old, backup or test, still reachable and years out of date.
- SFTP or hosting panel credentials that were sitting in someone’s inbox.
Useful evidence: files in wp-content modified in the last few weeks (the attacker’s files usually cluster around one date), the server access log around that date, and failed login counts if you have any logging at all.
3. Clean, or restore
If there is a backup from before that date, and the site has not changed much since, restore it. It is faster and you know it is clean.
If not, clean by hand:
- Replace WordPress core with a fresh copy of the same version: everything in wp-admin and wp-includes, and the root PHP files except wp-config.php.
- Replace every plugin and the theme with fresh downloads of the same versions. Do not trust the copies on the server.
- Go through wp-content/uploads and delete every .php file. There should be none.
- Delete plugins you do not recognise. Attackers install their own, often with a name that sounds like part of WordPress.
- Open wp-config.php and .htaccess and read them. Injected lines usually sit at the very top or very bottom.
- In the database, search the options table and post content for script tags and for long base64 strings. Check that the site address values have not changed.
- List the scheduled tasks. A task you did not create that runs every few hours is the reinfection mechanism.
Search terms that find most injected code: eval(, base64_decode(, gzinflate(, str_rot13(, and a long single line of nonsense characters at the top of a PHP file.
4. Rotate everything
Every admin password. The database password, in wp-config.php and in the hosting panel. SFTP. The hosting panel itself. Any API key the site holds, for payments, email or maps. The secret keys again, now that the cleanup is done. Skip one and you have left the attacker a key, and you will be doing this again.
5. Patch and harden
Update WordPress, every plugin and every theme to current. Delete the ones you do not use, since a deactivated plugin is still a file on the server. Set file permissions back to normal, 644 for files and 755 for folders. Turn off file editing in the dashboard. Put a firewall in front of the site, at the host, at Cloudflare or as a plugin. Require two-factor login for every administrator.
6. Watch for thirty days
A cleanup is not proven until a month has passed. Something should be checking the site every day for changed files, new admin users, new scheduled tasks and its Safe Browsing status. If the attacker left something you missed, this is how you find out on day two instead of when a customer emails you.
If Google flagged the site, request the review only after step five. Reviews that fail because the crawler still found something set you back days.
When to call someone
If you are past step two and cannot find the door, stop and get help. Cleaning without knowing the entry point is what produces the “it came back” story. And if the site takes payments or holds customer data, you may have a legal duty to report the breach, which is a separate conversation from the cleanup.
Our scanner will not clean a site, but it will tell you in ten seconds whether it is currently flagged, what versions of WordPress and PHP it runs, and what is exposed. That is a reasonable first look before deciding what to do.
See where your own site stands.
The scanner checks the things this guide talks about, in about ten seconds, no signup.
More from the guides
Is my website hacked? Twelve signs, and a five-minute check
Most hacked sites look normal to their owners for weeks. The signs show up in Google, in your inbox and on other people's phones first. Here are the twelve we check, and a five-minute routine that catches most of them.
Deceptive site ahead: what it means and the fix order
Chrome is not warning about your design. Google Safe Browsing found phishing or malware on your domain. Here is what the red screen means, how to find the cause, and how to get the flag removed without it coming back.
Security headers, explained by what our scanner sees
Five short lines in your server response stop most clickjacking, script injection and downgrade attacks. Most sites we scan send none of them. Here is what each one does, in plain terms, and how to add them on Apache, Nginx and Cloudflare.