Skip to main content
Wordpress

Cleaning Up a Hacked WordPress Site Your Agency Inherited

Quick answer

Cleaning up an inherited hacked WordPress site means containing it first (backup the infected state, restrict access, rotate every credential), finding the full scope before deleting anything, replacing core and plugins from official sources, closing the entry point, then hardening and verifying. Skip the scoping step and you’ll clean the symptom and leave the backdoor in place.

You take over a client site, run a quick check because something looks off, and find spam pages in Google that nobody on the client’s team wrote. Now it’s your problem, on a site you’ve never touched, and the client wants to know how bad it is.

Cleaning up compromised sites has been part of the job across 15+ years of WordPress work, and the lesson doesn’t change: the order matters more than the speed. Rush straight to deleting suspicious files and you’ll miss the thing that let the attacker in, and it comes right back. Here’s the sequence I use.

What should you do first, before touching anything?

Contain before you clean. On a site you didn’t build, you don’t yet know what’s normal, and deleting files immediately destroys your evidence of what actually happened.

  • Back up the infected state first. Files and database, before you touch anything. This is your evidence and your fallback if a fix goes wrong.
  • Restrict access. Maintenance mode, or a server-level password, so it stops serving malware or redirects while you work.
  • Rotate every credential. Hosting, SFTP/SSH, the database user, every WordPress admin account, and any API keys stored in plugins.

Do this before you open a single file. A compromised site with the old passwords still active is one an attacker can walk right back into while you’re cleaning it.

How do you find the full scope of a hack before cleaning it?

Deleting the obvious malware without mapping what else changed is the single most common reason a “cleaned” site gets reinfected within weeks. Work through the site systematically and write down what you find before removing anything.

  • Unknown admin users. List every administrator and confirm each one with the client. A rogue account is often the attacker’s real persistence method, not the malware itself.
  • Recently modified files. Sort by modification date across the whole install, not just wp-content.
  • PHP files inside wp-content/uploads. That directory should never contain executable PHP.
  • Injected code in wp-config.php, .htaccess, and functions.php. These load on every request and most people never read through them line by line.
  • Rogue cron events. Entries that re-download malware or re-create an admin user on a schedule are how a “clean” site gets reinfected days later.
  • Database injections. Check wp_options and wp_posts for spam links or hidden redirects.
  • Spam pages already indexed. Run a site: search on Google and check Search Console’s Security Issues panel.

Pull the admin list straight from the command line if you have WP-CLI access:

wp user list --role=administrator

How do you clean the site once you know the scope?

Clean from a position of certainty instead of guessing at what’s safe to keep. The rule I work by: if a file can’t be matched to a known, official source, it doesn’t survive.

  • Replace WordPress core entirely with fresh files, rather than patching the existing install.
  • Reinstall every plugin and theme from its official source, not the copies already on the server, even ones that look untouched.
  • Remove anything you can’t account for: an unfamiliar directory, an extra plugin, a file with an odd name in wp-content.
  • Clean the database entries flagged during scoping.
  • Delete the unknown admin users confirmed with the client as illegitimate.

WP-CLI will tell you exactly which core and plugin files don’t match the official release, faster and more reliable than eyeballing a file tree:

wp core verify-checksums
wp plugin verify-checksums --all

Anything flagged is either a genuinely modified file worth a closer look, or confirmation that a full reinstall from source was the right call.

How do you find and close the entry point?

Cleaning the malware without finding how it got in is why sites get hacked twice. It’s usually one of a short list: a vulnerable or abandoned plugin or theme, outdated core past its last security release, weak or reused admin credentials, or a leftover file from setup like an old installer script nobody removed.

If nothing explains it, widen the search to the hosting environment: a compromised neighbor on shared hosting, or a host account breached separately from WordPress. That’s a conversation with the host, not another pass through wp-content.

Where WordPress infections hide, and how to check for each one
Where it hides What to look for How to check
wp-content/uploads PHP files that shouldn’t exist in a media directory Search the uploads folder for any file ending in .php
wp-config.php Injected code above or below the normal config lines Diff the file against a known-clean backup, or read it line by line
.htaccess Unfamiliar rewrite rules or redirects you didn’t write Compare against WordPress’s default .htaccess block
Active theme’s functions.php Obfuscated code, base64 strings, or functions that don’t belong to the theme Reinstall the theme from its official source and diff the old file
wp_options / wp_posts tables Spam links, hidden redirect scripts, content nobody wrote Search the database for suspicious strings and unfamiliar post entries
WP-Cron Scheduled events that re-download malware or recreate admin accounts List scheduled cron events and confirm each one is expected
Admin users table Accounts nobody on the client’s team recognizes List every administrator and confirm each one by name

Sources: checks follow WordPress’s official hardening guide and the WP-CLI checksum docs. Infection figures from Sucuri’s 2023 Hacked Website & Malware Threat Report: WordPress made up roughly 95.5% of the infections Sucuri detected, and 39.1% of CMS applications were outdated at the point of infection.

That outdated-at-infection number is worth sitting with. Nearly two in five infected sites were just behind on updates when the attacker found them. On a site you’ve just inherited, checking what’s overdue is often the fastest lead on how they got in.

Key takeaways

  • Contain first: back up the infected state as evidence, restrict access, and rotate every credential before you touch a single file.
  • Map the full scope before deleting anything. An incomplete scan is the main reason a cleaned site gets reinfected.
  • Nearly 4 in 10 infected CMS installs were simply outdated when attacked, so checking what’s overdue is often the fastest lead on the entry point.
  • A cleanup isn’t done until you’ve closed the entry point and set up monitoring, otherwise you’re just waiting for the same infection to come back.

How do you harden and verify the site is actually clean?

Once the site is clean and the entry point is closed, lock it down and confirm the work held before you hand it back.

  • Rotate the security keys and salts in wp-config.php. This invalidates old cookies and sessions if the attacker had any account access.
  • Review file permissions. Anything more permissive than it needs to be makes the next attack easier.
  • Disable file editing from the dashboard. This stops an attacker who regains admin-level access from editing a theme or plugin file straight through wp-admin.
define( 'DISALLOW_FILE_EDIT', true );

Run a clean rescan after all of the above, then request a review in Search Console if the site was flagged for malware or deceptive content. Google won’t clear a warning on its own timeline; you have to ask, and only once you’re confident the site is actually clean. WordPress.org’s own hardening guide covers the file-permission and database-privilege details in more depth.

What do you owe the client after cleaning up a hack you didn’t cause?

You inherited the site, so you inherited the conversation about what happened. Handle it directly.

  • Document the incident. What you found, when, what you removed, and what the entry point turned out to be. A vague “it’s fixed” makes a client assume the worst the next time something goes wrong, related or not.
  • Set expectations plainly. A cleanup fixes what’s there today. It doesn’t guarantee tomorrow, especially if nobody’s watching for the next attempt.
  • Formalize what you actually inherited. Our website handoff checklist covers documenting a site’s access and history, which matters even more once you’ve had to clean one up mid-relationship.

If something else still doesn’t add up after the cleanup, run it against our WordPress troubleshooting guide or check whether it’s a straightforward plugin conflict before assuming the infection is back.

How do you keep an inherited site from getting hacked again?

Everything above is the starting point, not the finish line. The sites that stay clean are the ones someone is watching: updates on a schedule instead of queued up for months, backups running automatically off the server they protect, and someone checking for early signs instead of reacting once a client notices spam in the results. That ongoing watch is what a WordPress maintenance plan is built for.

Stop and escalate if you can’t identify the entry point after a real look, the same symptoms return after a cleanup you already did, the site touches WooCommerce or customer data, or you’re on the clock and don’t have the hours to scope it properly. A rushed cleanup that misses the entry point costs more time later than doing it right once. This is exactly what our WordPress project rescue service handles: an inherited, compromised site that needs the cleanup done completely and correctly the first time, under your agency’s brand, with a fixed quote before anything starts.

Frequently asked questions

How long does it take to clean a hacked WordPress site?

It depends on the scope, not just the amount of visible malware. One obvious injected script might take a few hours. A rogue admin account plus cron-based reinfection and spam already indexed in Google takes considerably longer, because scoping has to be thorough first.

Can I just restore from a backup instead of cleaning the site?

Only if you know the backup predates the compromise, and on an inherited site you often can’t be sure. A backup taken after the entry point opened just restores the same vulnerability. Confirm the timeline before trusting a restore as the fix.

Do I need to change every password, or just the WordPress admin login?

Every credential connected to the site: hosting, SFTP/SSH, the database user, all WordPress admin accounts, and any API keys stored in plugins. An attacker with access to one of those can often get back in even after the admin password changes.

How do I know if a plugin file is legitimate or part of the hack?

Don’t eyeball it file by file. Reinstall the plugin fresh from its official source and compare, or run a checksum verification against the official release. If a file doesn’t match what the developer actually shipped, it doesn’t belong on the site.

Will Google remove the “this site may be hacked” warning automatically once it’s clean?

No. Once you’re confident the site is clean and the entry point is closed, request a review through Search Console. Google re-crawls and re-evaluates the site before lifting the warning, which can take a few days, so don’t request it until the cleanup is genuinely finished.

JS
Written by John Schatz

John Schatz is the founder of WP SuperHelp, a white-label WordPress development and support partner for agencies. For over 15 years he and his team have built, fixed, and maintained WordPress sites under agency brands across 1,500+ client projects.

Let's talk about your next WordPress project

Get a free consultation and a fixed quote, usually within one business day, delivered under your agency's brand.

Get free consultation

Leave the daily management of your website in the hands of the WordPress specialists at WP SuperHelp.

Navigation