
Finding malware, spam links, or a defaced homepage on your WordPress site is unsettling, but panic is not a strategy. What matters is working through containment, cleanup, and hardening in the right order. Skip a step and the same door stays open for round two. This playbook walks through that order.
Step 1: Contain the Damage First
Before you clean anything, stop the bleeding.
- Take the site offline or into maintenance mode. This stops the malware from spreading further and stops search engines and visitors from seeing compromised content.
- Change your hosting account password immediately, even before you know the entry point. If an attacker has panel access, everything else you do can be undone behind your back.
- Preserve evidence. Copy the current (infected) files and a database export to a separate location before you start deleting anything. You will want this if you need to diagnose the entry point later, or if your host’s support team asks for logs.
- Check with your host about server-level isolation. If you’re on shared hosting, ask whether other accounts on the same server were affected; cross-account contamination happens more than people expect.
Step 2: Find the Entry Point
Cleaning without finding the entry point just buys you a few weeks before reinfection. Work through these in order:
- Check for outdated software. Run
wp core version,wp plugin list, andwp theme listto see what’s installed and how current it is. A known vulnerability in an old plugin or theme is the most common way in. - Review recent admin users. Run
wp user list --role=administratorand look for any account you don’t recognize. Attackers often create a hidden admin as a backdoor. - Check file modification times. Something like
find . -type f -mtime -30from the site root surfaces files changed recently, which is often a fast way to spot injected code. - Look at server and access logs for unusual POST requests to
wp-login.php,xmlrpc.php, or upload endpoints around the time the compromise likely started. If Cloudflare sits in front of your site, its firewall event log is a good second source, since it captures blocked and allowed requests at the edge before they ever reach your origin. - Rule out weak credentials. If there was no 2FA and no login attempt limiting, brute force is a very plausible entry point on its own, no vulnerable plugin required.
Step 3: Clean Core, Plugins, and Themes
The safest way to clean WordPress core is to replace it wholesale rather than trying to diff every file by hand:
wp core download --force
wp core verify-checksumsThis overwrites core files with known-good copies and then verifies them against WordPress.org’s checksums. For plugins and themes, the more reliable path is usually to delete anything you don’t actively need, then reinstall the rest fresh from the WordPress.org repository or the original vendor rather than trusting the copies currently on disk:
wp plugin deactivate --all
wp plugin delete
wp plugin install --activate Do this plugin by plugin rather than trusting a bulk update, since an update won’t necessarily remove a backdoor file that was added alongside a legitimate plugin folder.
Step 4: Clean the Uploads Folder
The wp-content/uploads directory should contain media, not executable code. Malware often hides PHP files here specifically because uploads are rarely audited. Search for anything that doesn’t belong:
find wp-content/uploads -name "*.php"In a properly configured install, this command should return nothing. Any PHP files it finds deserve close inspection and, in almost all cases, deletion.
Step 5: Clean the Database
Injected content in the database is just as common as injected files. Before editing anything, export a copy for reference:
wp db export backup-before-cleanup.sqlThen search for common injection patterns directly in SQL:
SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%base64_decode%';
SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%eval(%';
SELECT * FROM wp_options WHERE option_name IN ('siteurl','home');Check that siteurl and home point where you expect, since redirect malware often quietly changes these. Also check wp_options for unfamiliar entries and wp_usermeta for capability grants on accounts that shouldn’t have them. If you find widespread injected script tags across many posts, wp search-replace can help remove a known malicious string site-wide, but confirm the pattern is precise before running it broadly, since search-replace is not selective about context.
Step 6: Rotate Every Credential
This is the step people most often shortcut, and it’s the one that determines whether the attacker can walk back in.
- Reset passwords for all WordPress users, especially administrators, and enable 2FA if it isn’t already on.
- Change the database password and update
DB_PASSWORDinwp-config.php. - Rotate hosting panel, SFTP, and SSH credentials.
- Regenerate the authentication keys and salts in
wp-config.php. WordPress.org’s secret-key generator gives you fresh values; dropping them in invalidates every existing login cookie and session immediately. - Rotate any API keys used by plugins (payment gateways, email services, etc.) if there’s any chance they were exposed.
Step 7: Harden So It Doesn’t Happen Again
With the site clean and credentials rotated, close the doors that let the attacker in the first time:
- Enforce strong, unique passwords and 2FA for every account, and apply least-privilege roles so editors and authors aren’t sitting on admin capabilities they don’t need.
- Limit login attempts to blunt brute force.
- Disable XML-RPC if you don’t use it, since it’s a common target for both brute force and amplification abuse.
- Add
define('DISALLOW_FILE_EDIT', true);towp-config.phpso the theme and plugin editors can’t be used to inject code even if an account is compromised later. - Put Cloudflare in front of the site if it isn’t already, for edge caching, a WAF, bot mitigation, and DDoS protection, and keep the origin IP unpublished so attacks can’t route around the edge and hit your server directly.
- Set up (and actually test) off-site backups. A clean recent backup is the fastest recovery path if this ever happens again, but it’s only useful if you’ve verified you can restore from it.
- Run PHP 8.3 with OPcache enabled and keep core, plugins, and themes current going forward; most compromises exploit known, already-patched vulnerabilities.
Managed hosts vary in how much of this they handle for you. ServerBorn, for instance, runs Cloudflare’s edge, LiteSpeed, and Redis object caching by default and applies server-level hardening, but application-level hygiene, like keeping plugins updated and using 2FA, is still on the site owner.
Step 8: Verify and Monitor
Before you announce the site is back, confirm it. Run wp core verify-checksums again, recheck the uploads folder for stray PHP files, and search Google for your domain plus common spam terms to see if cached search results still show injected content (these can take time to clear even after your site is clean). Then keep an eye on things for the following weeks: watch for new unexpected admin users, unexplained outbound traffic, or search rankings dropping, all of which can signal a lingering problem you missed.
The Takeaway
A hacked WordPress site is recoverable, but only if you work through containment, entry-point discovery, full cleanup, and credential rotation in that order, then close the gap with real hardening. Skipping the entry-point step is the single most common reason sites get reinfected within weeks of a cleanup.