Do these three things before anything else

1. Take a full backup of the infected site — files and database. It's your evidence and your safety net.
2. Don't delete anything yet. Deleting the malware destroys the trail that leads to the backdoor.
3. If the site takes payments, put it in maintenance mode now. A compromised checkout can be skimming card data.

Step 1: Establish the scope

Before cleaning, find out how far it goes. On shared hosting, one infected site routinely contaminates every other site in the same account — clean one and the neighbour reinfects it within hours.

  • Do you host other sites on this account? Check every one of them.
  • Is the hosting account itself compromised? Look for SFTP users and SSH keys you didn't create.
  • Are there admin users you don't recognise? Check Users → All Users, and check the database directly — some malware hides accounts from the WordPress UI.
  • What does Google see? Search site:yourdomain.com and look for pages you never wrote. Check Search Console's Security Issues report.

Step 2: Find the entry point

This is the step everyone skips, and it's the reason cleanups fail. You are looking for the answer to one question: how did they get in?

Read the modification times

Files changed at 3 AM on a day you didn't deploy anything are your map. Over SSH:

# PHP files modified in the last 14 days
find . -name "*.php" -mtime -14 -ls

# PHP files hiding in the uploads directory — almost always malicious
find wp-content/uploads -name "*.php"

There is essentially no legitimate reason for a PHP file to exist inside wp-content/uploads/. If you find one, you've found a shell.

Read the access logs

Your host's access logs show the requests that preceded the first modified file. Look for POST requests to unusual paths, repeated requests to a specific plugin's endpoint, and the IP that keeps appearing. This usually names the vulnerable plugin outright.

Check plugin versions against known vulnerabilities

Cross-reference every installed plugin and its version against the WPScan vulnerability database. An outdated plugin with a published remote-code-execution bug is your most likely culprit — and once you can name it, you know exactly what to patch.

Step 3: Replace, don't disinfect

Trying to surgically remove malicious code from infected files is slow and unreliable. Replace instead:

  1. WordPress core. Delete wp-admin/ and wp-includes/ entirely and upload fresh copies of the exact same version. Never trust files you can't verify.
  2. Plugins and themes. Delete every one and reinstall from the official repository or your paid vendor. Any plugin that's no longer maintained does not come back.
  3. The root files. Compare index.php, wp-config.php, and .htaccess against clean references. Malware loves .htaccess redirect rules.
  4. wp-content/uploads. Keep your media, but delete every executable file. Images only.

Step 4: Clean the database

File cleanup alone misses a whole category of infection. Check for:

  • Injected scripts in post content — search wp_posts for <script, eval(, and iframe tags you didn't add.
  • Rogue entries in wp_options — particularly anything auto-loaded, which runs on every page load.
  • Unauthorised administrators in wp_users / wp_usermeta. Compare against the list you expect.
  • Malicious scheduled tasks in the cron option — a favourite persistence trick that re-downloads the payload after you clean it.

Step 5: Rotate every credential

Assume everything the site could reach is compromised, because it probably was:

  • Database password (update wp-config.php to match)
  • Hosting control panel and SFTP/SSH — and delete any keys you don't recognise
  • Every administrator password
  • The WordPress salts in wp-config.php — regenerate them from the official salt service. This force-logs-out every session, including the attacker's.
  • Any API keys stored on the site: payment gateways, SMTP, third-party integrations

Step 6: Get delisted

Only after the site is verifiably clean. A rejected reconsideration request makes the next one slower, so verify first with an independent scan, then in Search Console open Security & Manual Actions → Security Issues and request a review. Typical turnaround is a few days.

Browser warnings from Google Safe Browsing usually clear automatically once Google recrawls, but the Search Console request accelerates it.

The reinfection trap

If your site was cleaned before and got infected again, the previous cleanup removed the payload and left the door open. Backdoors hide in files that look completely ordinary — a few bytes appended to a legitimate theme file, a fake wp-cache.php in the root, or a rogue mu-plugin. Scanners find the obvious ones. Naming the entry point is the only way to know you're actually done.

Want it done properly, once?

Full cleanup: entry point identified, every backdoor removed, credentials rotated, hardened, plus a written forensic report naming how they got in.

FAQ

How did my WordPress site get hacked?

The large majority of compromises come through an outdated plugin with a known vulnerability. The rest are mostly weak or reused admin passwords, a compromised hosting account, or contamination from another site on the same server.

Why does my site keep getting reinfected?

Because the cleanup removed the payload but not the entry point. Attackers leave backdoors in ordinary-looking files and often create hidden admin accounts. Until the original vulnerability is closed and every credential rotated, they simply come back.

Can I just restore from a backup?

Only if you know the backup predates the infection and you patch the vulnerability immediately after restoring. Most compromises go unnoticed for weeks, so the convenient recent backup is often already infected.

Is a security plugin enough to clean it?

For removing obvious payloads, often yes. For finding backdoors and identifying the entry point, no — that requires reading logs and file timestamps, which no scanner does for you. That gap is exactly why reinfection is so common.