Patching WordPress 7.0.2 closes the door on the wp2shell exploit chain — but it does nothing to undo damage that happened while your site was still exposed. With active, in-the-wild exploitation confirmed since the July 17 disclosure, that gap matters. If your site ran an affected version even for a few days, the honest question isn’t “am I patched now?” It’s “was I already hit?”
I’ve spent the past two weeks auditing client sites after this incident, and I want to walk you through exactly how I check whether a WordPress site has been compromised — and the precise steps I take to clean one up and lock it down. This is the process, not a plugin pitch.
First, understand what you’re actually looking for
The wp2shell chain combined a SQL injection flaw (CVE-2026-60137) with a REST API route-confusion bug (CVE-2026-63030) to achieve unauthenticated remote code execution. In plain terms: an attacker could run their own code on a default install without ever logging in. When that happens, the goal is almost always persistence — a hidden way back in — followed by monetization: spam injection, malicious redirects, card skimming, or using your server to attack others.
So I’m not hunting for one dramatic sign. I’m looking for the quiet footprints of someone who wanted to stay unnoticed.
The signs that make me suspicious
Before touching any files, I look for behavioral tells. Any one of these is worth a full audit:
- Admin users you don’t recognize, or existing accounts whose email addresses have quietly changed.
- Unexpected outbound traffic or a sudden spike in server load with no marketing reason behind it.
- Google Search Console warnings, or search results for your brand showing pharma, casino, or replica-goods keywords you never published.
- Redirects that only fire for mobile visitors or first-time referrals from Google — a classic cloaking trick that hides the attack from you while you’re logged in.
- New scheduled tasks in WP-Cron, or files with recent modification dates in
wp-adminandwp-includes, which should almost never change between core updates.
How I confirm it: the file-level check
Behavioral signs raise the flag; the filesystem confirms it. Here’s the order I work in.
1. Verify core integrity
WordPress core files are identical to the official release, so any difference is a red flag. If you have WP-CLI access, wp core verify-checksums compares every core file against WordPress.org’s published hashes and lists anything that’s been altered or added. It’s the fastest, most reliable first pass I know of.
2. Hunt for shells and injected code
Web shells love to hide in the uploads directory, where PHP should never execute. I search for .php files under wp-content/uploads — there should be none. I also grep the codebase for the functions malware leans on: eval(, base64_decode(, gzinflate(, and str_rot13(. Legitimate plugins occasionally use these, so a match isn’t a conviction — but a long, obfuscated one-liner at the top of an otherwise normal file usually is.
3. Check the database
Code isn’t the only hiding place. I inspect the wp_options table for suspicious autoloaded entries, scan wp_users and wp_usermeta for accounts with an administrator capability I didn’t create, and look through post content for injected <script> tags or hidden spam links.
What to do the moment you find something
If the audit turns up a compromise, resist the urge to just delete the one bad file and move on. Attackers plant redundancy. Here is the sequence I follow, and the order genuinely matters.
Take a snapshot before you touch anything
Back up the current, infected state — files and database both. It feels counterintuitive, but you may need it as forensic evidence, and it protects you if a cleanup step breaks something you can’t yet explain.
Isolate the site
Put WordPress into maintenance mode or restrict access at the server level. This stops attackers from re-infecting while you’re cleaning, and it protects your visitors from whatever’s being served.
Rotate every credential
Change all admin passwords, generate fresh secret keys in wp-config.php, reset your database password, and rotate hosting and FTP/SFTP logins. Then update the wp-config.php salts so every existing session is forced to log in again — including the attacker’s.
Replace core, plugins, and themes from clean sources
Don’t try to surgically clean core files. Re-download WordPress and every plugin and theme from official sources and replace them wholesale. Delete anything you don’t actively use — dormant plugins are pure attack surface. For custom code, compare it against your version control, never against the copy sitting on the possibly-compromised server.
Clean the database by hand
Remove the rogue admin users, injected options, and any spam content you flagged during the audit. Databases usually need manual attention because automated scanners are cautious about touching content tables.
After the cleanup: closing the loop
Once the site is clean, I confirm it’s actually on a patched release — 7.0.2, 6.9.5, or 6.8.6 depending on your branch — rather than assuming the forced auto-update completed. Verify the real version; don’t trust the dashboard blindly.
Then I request a review through Google Search Console if the site was blacklisted, monitor logs closely for a week or two, and set up file-integrity monitoring so the next unexpected change surfaces in hours instead of weeks. If card data or customer accounts were ever exposed, that’s a disclosure conversation, not just a technical one — treat it accordingly.
The uncomfortable takeaway
Auto-updates are a genuine safety net, and WordPress forcing them here saved a lot of sites. But “patched” and “safe” are not the same word. If your site was reachable while running a vulnerable version, assume nothing and verify everything. Twenty minutes of checking now is far cheaper than discovering a skimmer on your checkout page three months from today.
If you’d rather not run this audit yourself, that’s exactly the kind of work I do — reach out and I’ll take a look.
Comments
No comments yet. Be the first to share your thoughts!
Leave a Comment