Work in this order. The instinct is to delete the bad files immediately — doing that first destroys the evidence of how they got in, which is how sites get compromised twice.
Download a complete copy of the files and database before you clean anything. It is the only record of how the attacker got in, and cleaning overwrites it. Keep it somewhere isolated — it contains live malware.
Then put the site into maintenance mode. Every minute it stays up it may be serving malware to visitors and deepening a search engine penalty.
Not every strange symptom is an attack. A blank page is usually a plugin conflict, and a database error is usually a credentials problem. What distinguishes a compromise is content or behaviour nobody on your team created.
.php files inside wp-content/uploads, where executable code never belongsMany attacks specifically hide from logged-in administrators, serving clean pages to you and spam to everyone else. Check in a private window, from a different network, and look at what search engines have indexed for your domain. The version of your site that Google sees is often the one carrying the payload.
Full file and database copy, stored offline and clearly labelled as infected. Also download your server access logs if the host provides them — they often show the request that established access, and the timestamp narrows which backup is safe.
Maintenance mode or an offline holding page. If the host has suspended the account, leave it suspended while you work; arguing for reinstatement before cleaning wastes time you need.
Hosting control panel, FTP and SFTP accounts, the database user, and every WordPress administrator. Then replace the salts in wp-config.php — the block of keys beginning AUTH_KEY. Fresh values are generated by the WordPress salt API, and replacing them invalidates every existing session, ejecting anyone still logged in. Changing passwords without this leaves active sessions intact.
Remove administrator accounts you cannot account for. Check registration dates against the incident window. Also check whether new user registration was silently enabled and the default role set to administrator, which is a quiet, common persistence trick.
If you have a backup from before the compromise, restoring is faster and materially more trustworthy than cleaning — you are replacing an unknown state with a known one. The trap is that a restore also reinstates the vulnerability, so step 6 is not optional.
Without a clean backup, replace rather than repair: delete WordPress core files and reinstall the same version fresh, then reinstall every theme and plugin from source. Keep only wp-config.php (after inspecting it) and wp-content/uploads (after checking it for executable files).
This is the step that determines whether you are back here next month. Update WordPress core, every plugin and every theme. Delete anything unused. Identify which component was vulnerable — the logs and the disclosure timeline usually make this clear — and if it is abandoned by its author, replace it rather than reinstalling it.
Scan again, check the site from outside as an anonymous visitor, and confirm search results are clean. If the site was flagged, request a review through Google Search Console. Reviews fail most often because a backdoor was missed — so verify properly before submitting rather than submitting hopefully.
The uncomfortable finding in almost every WordPress post-mortem is that the vulnerability had been patched before the site was compromised. The exploit was available, the fix was available, and the update had not been applied.
A disclosed vulnerability in a plugin you have standardised across a client portfolio is not one incident, it is a countdown across every site running it. The response that matters is measured in hours, and it has to be one action across the fleet rather than a queue of logins.
Recovery is also where snapshot history earns its keep. Knowing precisely what changed and when — and being able to reverse a specific change rather than rolling an entire site back to last night — is the difference between a contained incident and a lost day of client data.
Managing multiple WordPress sites covers fleet-wide updates, and one-click undo covers reversing individual changes.
Common signs are unexpected redirects to other sites, spam content or pages you did not create, a browser or search engine warning, administrator accounts you do not recognise, unfamiliar files in the uploads directory, a sudden traffic or performance change, and your host suspending the account. Search engines often notice before the site owner does.
Restore if you have a backup from before the compromise and can identify roughly when it happened — it is faster and more reliable than hunting for injected code. But restoring alone is not enough: it returns the site to the state that was vulnerable, so you must patch the entry point immediately afterwards or you will be compromised again.
Overwhelmingly through a known vulnerability in an outdated plugin or theme, rather than a targeted attack. Automated scanners look for specific vulnerable versions across the entire web and exploit whatever they find. Weak or reused administrator passwords and compromised hosting credentials account for most of the remainder.
Salts are cryptographic keys in wp-config.php used to secure login cookies. Replacing them invalidates every active session, which forces any attacker still logged in to be logged out. Changing passwords without replacing salts leaves existing sessions valid — a step people frequently miss.
Almost always a backdoor that survived the cleanup, or an entry point that was never closed. Backdoors are often placed far from the original infection — in the uploads directory, a mu-plugin, or a legitimate-looking core file — specifically so that cleaning the visible damage does not remove them. Reinstalling core, themes and plugins from fresh source files is more reliable than selective cleaning.
One instruction across your whole portfolio, with a snapshot before every change.
Start free