The first thing to understand about a hacked WordPress site is that the visible damage is rarely the point. Defacement is loud and rare. What is common is quiet: code that shows spam to Google while showing your normal site to you, or a script that loads something harmful in your visitors’ browsers.
That is why so many owners discover a compromise not by looking at their site, but by getting a Search Console warning, or noticing the site has become inexplicably slow.
This is the order to work in, and — more importantly — the two mistakes that cause people to get hacked again a week later.
The two mistakes
Mistake one: cleaning the files without finding how they got in. Remove the malicious code and leave the door open, and it comes back. Often within days, because the same automated process that placed it the first time is still running.
Mistake two: changing passwords but not the WordPress salts. Salts are the secret keys in wp-config.php that sign login cookies. An attacker with a valid session cookie stays logged in after you change the password, because the cookie is still signed correctly. Rotating the salts invalidates every session on the site, including theirs.
Do both, or expect to do this again.
Step 1 — Preserve evidence before you touch anything
Resist the urge to start deleting. Take a full copy of the files and a database export first, and keep server access logs if your host provides them.
You need this for two reasons: to work out the entry point, and because you will occasionally delete something you shouldn’t and need it back. Restoring an old backup immediately is tempting and usually wrong — it destroys the evidence and often restores the infection along with everything else.
Step 2 — Close access before cleaning
Rotate everything, in this order:
- Hosting control panel password
- FTP / SFTP and SSH credentials
- Database password — then update
wp-config.phpto match - All administrator passwords
- The eight salt values in
wp-config.php
The database password is the one people skip, and it is genuinely dangerous to skip. An attacker with database credentials does not need a file backdoor at all. They can insert an administrator account straight into the users table, which leaves no trace in your files and survives every file cleanup you perform.
A useful tell: an admin account with no email address, or a registration date from before your site existed, was almost certainly inserted directly via SQL. WordPress’s own user creation would never produce either.
Step 3 — Find the malicious code
Compare rather than hunt. Replace WordPress core with a clean official download of the same version, keeping wp-config.php and wp-content. Then run an integrity check.
Two things that catch out even careful people:
Core integrity checks do not cover your theme. A check that reports “verifies against checksums” is telling you core is clean and saying nothing whatsoever about your theme or plugins. Malware placed in a theme file passes that check every time.
Look at JavaScript, not just PHP. Most guides focus on PHP backdoors. Increasingly the payload is client-side — appended to a legitimate theme script so it loads on every page. Signatures worth grepping for across theme and plugin files:
- Hex-style variable names like
_0x4f2a atob(paired withnew Function(- Very long base64 strings inside otherwise ordinary code
eval(,document.write,String.fromCharCodeloops
A related trick worth knowing: code hidden at the end of the opening PHP tag, padded with tabs so it sits far off the right edge of an editor. The file appears to begin with a normal <?php, and the malicious include is invisible unless you scroll or check the line length.
Step 4 — Check what your visitors are being shown
Because the point of most infections is to show different things to different people, checking the site in your own browser proves very little — many payloads disable themselves for logged-in users specifically so the owner sees nothing.
Do this instead:
- Open the site in a private window, logged out
- Use the URL Inspection tool in Search Console and read the fetched HTML — that is what Google actually receives
- Search
site:yourdomain.comand look for pages you never created - Request the homepage with a Googlebot user agent and compare it byte-for-byte with a normal request
If the two responses differ in content, you are looking at cloaking.
Step 5 — Check the database and users
Look for injected <script> or <iframe> tags in post content, unexpected options, unfamiliar scheduled tasks, and administrator accounts you do not recognise. Also check for PHP files inside your uploads directory — there is never a legitimate reason for one to be there.
Step 6 — Verify, then wait, then verify again
After cleaning: integrity check passes, no obfuscated code in theme or plugin files, no unknown admins, uploads free of PHP, response identical for crawlers and humans, no unexplained slowness.
Then check again after 48 hours. Re-infection is the signal that the entry point is still open, and it is better to discover that yourself than through a second Google warning.
Step 7 — Only then, request review
If Search Console flagged a security issue, request the review after the site is genuinely clean and the vector is closed. Requesting it early and failing makes the second attempt slower.
Hardening that actually pays for itself
| Control | Prevents |
|---|---|
Block PHP execution in /uploads/ |
Uploaded webshells running |
DISALLOW_FILE_EDIT |
Theme editing from a stolen admin session |
Deny direct access to wp-config.php |
Credential exposure via misconfiguration |
| Keep core, themes and plugins updated | The most common entry route by a wide margin |
| Remove unused themes and plugins | Vulnerabilities in code you forgot you had |
| Two-factor on admin accounts | Credential reuse and brute force |
| Alerting on new admin accounts | Silent persistence going unnoticed |
That last one matters more than it looks. If an attacker can write to your database, no PHP-level control will stop them creating an account — but noticing within hours instead of months changes the outcome entirely.
Frequently asked questions
How did my WordPress site get hacked?
Most often an outdated plugin or theme with a known vulnerability, then reused or stolen credentials, then weak hosting isolation. Nulled premium themes are a reliable source of pre-installed backdoors.
Can I just restore a backup?
Only if you know the backup predates the infection and you have closed the entry point. Otherwise you restore the malware or get reinfected immediately. Restoring is also how people destroy the evidence they needed.
Will a security plugin remove everything?
Scanners catch known signatures and are worth running, but they miss novel or well-hidden payloads — particularly obfuscated JavaScript inside a legitimate theme file. Treat a clean scan as encouraging, not conclusive.
My site looks fine. Can it still be hacked?
Yes, and this is the normal case. Payloads that target search engines deliberately hide from logged-in administrators. Unexplained slowness, a Search Console warning, or unfamiliar pages in site: results are the signals to watch.
How much does professional cleanup cost?
It varies with how deep the compromise goes and whether the entry point is obvious. The larger cost is usually elsewhere: lost rankings while a warning is live, and lost trust if browsers start warning your visitors.
Why is my hacked site so slow?
A common cause is malware calling an external server on every page load. If that server stops responding, every page waits out the connection timeout before rendering. It presents as a hosting problem and is not one — check server response time against database and static asset timing to tell the difference.
If you are dealing with this now
Take the backup, rotate every credential including the database password and the salts, and only then start removing code. That order is what stops it happening twice.
If you would rather not do it yourself, our website maintenance work covers cleanup, hardening and monitoring, and what a technical SEO audit actually finds describes how this kind of problem usually surfaces in the first place.
