If your site is redirecting to a pharmacy in Moscow right now, do these four things before reading further: put the site in maintenance mode, change your hosting and WordPress admin passwords, download a full backup of the site as it is (yes, infected), and email your host to ask if they’ve logged anything.
That buys you an hour. The rest of this guide is what to do with that hour and the day after it.
A typical WordPress hack cleanup takes 3 to 8 hours for a standard infection and one to two days for a badly compromised store. Professional rates run $150 to $500, more if there’s card data involved. If you’d rather hand it off, our team does emergency WordPress malware removal and we’ll tell you honestly whether it’s a cleanup or a rebuild after looking at it.
If you want to do it yourself, keep going.
Make sure it’s actually hacked
Most people know because something obvious happened. Visitors get bounced to gambling or pharma pages. Google Search Console has a red banner under Security Issues. Chrome shows “Deceptive site ahead” on your homepage.
Your host suspended the account and sent a form email about malware. Someone on Facebook asks why your site is selling Viagra.
The sneaky version is worse. Japanese keyword hack (spammy Japanese product listings appearing in Google results for your domain, thousands of them), a phishing page for a bank sitting in /wp-content/uploads/2024/03/secure-login/, or a cryptominer eating your CPU with no visible change on the front end. You find these when Google emails you, or when a customer’s IT department blocks your domain.
Two checks that take five minutes. Open Search Console, go to Security & Manual Actions > Security Issues. Google’s crawler has already seen your site from outside and it doesn’t miss much. Then search site:yourdomain.com and scroll past page one.
Injected pages tend to show up on pages three through ten, with titles in languages you don’t publish in.
A slow site or a broken plugin isn’t a hack. A hosting outage isn’t a hack. If none of the symptoms above match, you’re probably looking at a bug, and that’s a different article.
The order matters
People skip straight to deleting files. Don’t. Cleanups fail because the attacker still has a working password while you work, or because you deleted the evidence that would’ve shown you how they got in.
1. Contain it. Maintenance mode if the site is just serving spam. Fully offline (a static holding page, or ask your host to suspend public access) if it’s phishing, stealing card data on a WooCommerce checkout, or pushing malware downloads to visitors. Lost sales for a day are cheaper than a chargeback wave or a data breach notification.
2. Rotate every credential. WordPress admin accounts, all of them. The hosting control panel. SFTP/FTP. The database user in wp-config.php. Your salt keys (regenerate at api.wordpress.org/secret-key/1.1/salt/ and paste them in). Any email address that can reset any of those. If you have API keys for payment gateways stored in plugin settings, rotate those too. This is the step most DIY cleanups skip and it’s why the site is hacked again on Thursday.
3. Back up the infected site. It feels wrong. Do it anyway. You’ll need the infected copy to find the entry point, and if you break something mid-cleanup you can’t investigate files that no longer exist. Full files plus a database dump. Store it somewhere off the server.
4. Check what your host has. Most managed hosts keep daily snapshots for 14 to 30 days. Ask for the list. Ask for access logs from the last two weeks. Some hosts (SiteGround, Kinsta, WP Engine) will scan for you on request. Take the free help.
After those four, you either restore or clean.
Restore from a clean backup, if you can
This is faster and more reliable than manual cleaning, and I’ll say it plainly: if you have a backup that’s definitely older than the infection, restore it. Don’t clean.
The problem is knowing the backup is clean. Infections often sit dormant for weeks before the payload activates. A backup from last Tuesday might already contain the backdoor. So check the backup before trusting it: look at the file modification dates in the archive, grep it for eval(base64_decode, gzinflate(, str_rot13(, and preg_replace with the /e modifier. Look for .php files anywhere under wp-content/uploads. If it’s clean, restore it, then immediately update everything and rotate credentials again, because whatever hole let them in is still in that backup.
If the newest clean backup is three months old and you’d lose a lot of content, you can restore the files from the old backup and carefully bring the database forward from the current one after cleaning it (database cleaning is covered below).
That’s a middle path that works well for blogs. It works badly for WooCommerce stores where the order and customer data lives in the database and might itself be tampered with.
Manual cleanup, file by file
No clean backup means you’re cleaning by hand. Budget half a day.
Start by running a scanner so you have a list. Wordfence and MalCare both do a decent job on file-level malware; neither is perfect and both miss database injections regularly. Your host’s cPanel might have ImunifyAV, which is worth running as a second opinion. Treat the scan results as a starting list, not a finish line.
Then replace WordPress core. Download the exact version you’re running (check wp-includes/version.php) from wordpress.org, delete wp-admin and wp-includes on the server, upload the fresh ones. Don’t touch wp-content or wp-config.php yet. Compare the root files (index.php, wp-load.php, wp-settings.php, .htaccess, wp-config.php) against the fresh copy line by line. .htaccess is a favourite spot for redirect rules; wp-config.php sometimes gets an extra include line at the very bottom, after hundreds of blank lines so it’s off-screen in the editor.
Plugins and themes next. For each active plugin, delete the folder and reinstall fresh from wordpress.org or the vendor. Don’t update over the top, delete and reinstall. Attackers put backdoor files inside legitimate plugin folders with names like wp-cache.php or class-wp-widget.php, and an update won’t remove files it doesn’t know about.
Same for the theme. If you’ve customised a theme directly instead of using a child theme, this is the painful part, and it’s a good argument for child themes.
Delete every inactive plugin and theme. The old Twenty Twenty-One theme sitting inactive is still a place to hide a shell.
Then wp-content/uploads. There should be no PHP files here at all. Run this over SSH:
find wp-content/uploads -name "*.php" -o -name "*.phtml" -o -name "*.php5"
Anything it finds is malicious or a plugin doing something it shouldn’t. Delete them. While you’re in the terminal, look for recently modified files across the whole install:
find . -type f -mtime -14 -name "*.php"
That lists PHP files changed in the last two weeks. On a site you haven’t updated recently, this list should be short. Read every file on it.
Check wp-content/mu-plugins. Must-use plugins load automatically and don’t appear in the normal plugin list, which makes it a nice quiet home for a backdoor. Many sites have no legitimate reason for this folder to exist.
Look for a second wp-config.php or a fake wp-login.php in unexpected directories. Look for .ico files that are actually PHP (attackers rename them; file suspicious.ico on the command line will tell you). Look for folders with names like .well-known, cgi-bin, or old that contain PHP.
Finally, file permissions. Directories 755, files 644, wp-config.php 600 or 640. If everything is 777, something upstream is wrong and you should raise it with your host.
The database is where cleanups fail
You can replace every file on the server and still be hacked, because the injection is in the database. This is the step most guides skim and most DIY cleanups miss entirely.
Open phpMyAdmin or Adminer. Start with wp_users: any admin you don’t recognise gets deleted, and check wp_usermeta for accounts that have administrator capabilities but appear as subscribers in the admin list (attackers edit the meta so the account looks harmless).
Then wp_options. The rows to inspect are siteurl, home, and active_plugins (look for plugins that don’t exist in the plugins folder). Search the whole table for <script, eval(, base64, and any domain you don’t own. Widgets are stored here too (widget_text, widget_custom_html) and it’s very common for an injected script tag to be sitting in a text widget nobody has looked at since 2019.
wp_posts gets injected content in post_content, usually a script tag or a hidden div with spam links at the bottom of every post. Run:
SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%<script%' OR post_content LIKE '%eval(%' OR post_content LIKE '%iframe%';
Also check post_type = 'post' with post_status = 'publish' for posts you didn’t write. Japanese keyword hacks create thousands of these, often with a post_date in the past so they sit below your real content.
wp_postmeta can carry the same payloads, and on WooCommerce sites there are scheduled actions in wp_actionscheduler_actions that attackers have used to re-inject on a timer. If you have a cron-based reinfection (site clean at 5pm, dirty at 6am), look here and at wp_options for the cron row.
Your table prefix might not be wp_. Check wp-config.php for $table_prefix.
Find the entry point or you’ll be back here
Cleaning without finding the cause is a temporary fix. Roughly speaking, hacks come through an outdated plugin or theme with a known vulnerability, a weak or reused password (often the hosting account, not WordPress), a nulled premium theme or plugin that shipped with the backdoor built in, or a neighbouring site on the same hosting account that was compromised and used to walk into yours.
The access logs from your host will usually show it. Look for POST requests to unusual files in the days before symptoms started, especially anything under wp-content that shouldn’t be accepting POSTs. Wordfence’s login log will show brute-force patterns. Check the vulnerability databases (WPScan, Patchstack) for every plugin you were running at the version you were running it.
If you can’t find it, assume it was the most out-of-date plugin you had. Delete it if you can live without it.
Whatever the cause, update everything now: core, every plugin, every theme, PHP itself (anything below 8.1 is unsupported and should worry you). Turn on two-factor authentication for every admin.
Rename or move the login page if you’re getting hammered by brute force, though honestly a strong password plus 2FA does more than any login-URL trick.
Getting Google to trust you again
Once you’re confident the site is clean, go back to Search Console > Security Issues and click Request Review. Write two or three plain sentences: what the infection was, what you did about it, what you changed so it won’t recur. Google’s team reads these. Vague requests get rejected; specific ones usually clear in 24 to 72 hours.
If Chrome is showing the red interstitial, that’s Safe Browsing, and it clears from the same review. Other blocklists (McAfee SiteAdvisor, Norton Safe Web, various email spam lists) have their own delisting forms and can take a week or more. Check yours at VirusTotal by entering your domain; it shows which vendors are flagging you.
Resubmit your sitemap. If the hack created thousands of spam URLs, those will drop out of the index on their own once they 404, but you can speed it up with the Removals tool for the worst directory (e.g. yourdomain.com/product/ if the fake pages all lived there).
Traffic recovery is slow and annoying. Expect two to six weeks of depressed organic traffic after a Safe Browsing warning even once it’s cleared. There’s nothing to do about this except not get hacked again.
When to stop and call someone
Do it yourself if it’s a brochure site, the symptoms are visible, you’re comfortable with SFTP and phpMyAdmin, and you have a day to spend.
Get a professional WordPress developer involved if any of these apply: it’s a WooCommerce or membership site with customer data (there may be legal reporting obligations, and you don’t want to be the one who quietly cleaned it up without knowing what was taken); the infection came back after your first cleanup, which means a backdoor survived; Google has blocklisted you and every day offline costs real money; or you’re staring at a scan report with 340 flagged files and no idea where to start.
Be suspicious of anyone quoting a one-hour fix. Removing the visible malware takes an hour. Verifying the site is clean, finding the entry point, and closing it takes the rest of the day, and skipping that part is how sites end up paying for two cleanups.
What actually prevents the next one
The site got hacked because nobody was updating it, nobody was monitoring it, and the backups either didn’t exist or were on the same server as the infection. Those three conditions are still true after cleanup unless you change them.
WordPress maintenance that includes weekly updates, malware scanning, and offsite backups costs less per year than one emergency cleanup. Pair it with hosting that runs server-level malware scanning and the next vulnerability disclosure becomes a routine update notification rather than a weekend spent in phpMyAdmin.
If you’re reading this because you’re hacked now and need it fixed today, send us the URL and what you’re seeing. We’ll look at it and quote before we touch anything.
Frequently asked questions
How long does a WordPress hack cleanup take? Three to eight hours for a typical infection on a brochure site. One to two days for a WooCommerce store, a site with multiple backdoors, or one where the database has been heavily injected. Anyone promising an hour is only removing what’s visible.
How much does it cost to clean a hacked WordPress site? Professional cleanups usually run $150 to $500. Expect the top of that range or above for e-commerce sites, sites with card data exposure, or ones that need a partial rebuild. Most reputable services quote a fixed fee after a quick look rather than billing hourly.
Can I just delete the malware files and move on? You can, and the site will probably be reinfected within a week. Hacks almost always leave more than one backdoor, often in the database or in places a file scanner doesn’t check. Deleting the obvious file removes the symptom, not the access.
Should I restore from a backup or clean manually? Restore, if you have a backup you’re sure predates the infection. It’s faster and more reliable. The catch is that infections often sit dormant for weeks, so check the backup for PHP files in uploads and encoded strings like base64_decode before trusting it, and patch the vulnerability immediately after restoring or you’ll be back where you started.
Why does my WordPress site keep getting hacked? Because the entry point was never closed. Either a backdoor survived the last cleanup, an outdated plugin is still installed, a password was reused somewhere, or another site on the same hosting account is compromised and being used as a bridge. Reinfection is a diagnostic clue, not bad luck.
Will my Google rankings recover after a hack? Yes, but slowly. Once Search Console’s review clears (usually 1 to 3 days after you request it), expect two to six weeks of reduced organic traffic before it returns to normal. Spam URLs the hack created will drop out of the index on their own as they 404.
Do I need to tell my customers? If it’s a store or membership site and there’s any chance customer data was accessed, yes, and depending on where you and your customers are you may be legally required to (GDPR gives you 72 hours to notify the regulator). This is one of the main reasons to bring in a professional for e-commerce hacks: you need to know what was taken, not just that the site is clean now.
Is Wordfence enough to clean a hacked site? It’s a good starting point for file-level malware and it’ll catch a lot. It regularly misses database injections, backdoors in mu-plugins, and anything hidden inside legitimate plugin folders. Use it to build your list, then do the manual checks.