,

·

How to clean up and secure WordPress after the wp2shell attack

Patching isn’t enough after wp2shell (CVE-2026-63030). Remove backdoors, reset passwords, and clean your WordPress database with this step-by-step guide.

Last updated: July 22, 2026 · Skill level: intermediate — you will need FTP or SSH access to your server and the ability to run database queries.

If your site ran WordPress 6.9.0–6.9.4 or 7.0.0–7.0.1 in July 2026, assume attackers could have reached it through the wp2shell vulnerability. Recovery takes four steps: update to WordPress 6.9.5 or 7.0.2, remove backdoor files, reset every password and session, and delete malicious database records. Patching alone is not enough — this guide walks through the full cleanup.

What is the wp2shell vulnerability?

wp2shell is the nickname for a pair of WordPress core flaws — CVE-2026-63030, a REST API batch-route confusion, and CVE-2026-60137, a SQL injection — that chain together into unauthenticated remote code execution. An attacker needs no account and no vulnerable plugin: a default WordPress installation is enough.

The attack goes through the WordPress REST API batch endpoint (/wp-json/batch/v1). Attackers combined the two flaws and used MySQL’s INTO OUTFILE statement to write PHP webshells directly to disk. According to research published by Wiz (July 2026), 60% of organizations running WordPress had at least one vulnerable instance when the flaws were disclosed on July 17, 2026, and 25% were exposing a vulnerable server to the internet. Exploitation in the wild was confirmed by July 18–20, 2026.

The flaws were reported by researchers at Searchlight Cyber. WordPress shipped the fixed releases 6.9.5 and 7.0.2 on July 17, 2026, according to Rapid7’s emerging threat report.

Which WordPress versions are affected by wp2shell?

WordPress 6.9.0–6.9.4 and 7.0.0–7.0.1 are vulnerable to the full remote-code-execution chain. WordPress 6.8.0–6.8.5 is affected by the SQL injection component only. The first patched releases are 6.9.5 and 7.0.2, published July 17, 2026.

CVETypeAffected versionsFixed in
CVE-2026-63030REST API batch-route confusion (pre-auth)6.9.0–6.9.4, 7.0.0–7.0.16.9.5 / 7.0.2
CVE-2026-60137SQL injection in WordPress core6.8.0–6.8.5 (SQLi only); 6.9.0–7.0.1 (chained to RCE)6.9.5 / 7.0.2

How do I know if my site was compromised?

Check the locations in the table below. A patched site can still carry a backdoor that was planted before you updated, so the update itself tells you nothing about whether you were breached. Attack traffic in your access logs — POST requests to /wp-json/batch/v1, HTTP 207 responses, or user agents containing “wp2shell” — is the clearest signal.

Where to lookWhat to look for
/wp-content/cache/PHP files with random names (e.g. e042u9xy9ra1.php) — cache folders normally hold generated HTML, CSS, and JS, not standalone PHP
/wp-content/mu-plugins/Files you did not install, often posing as a security patch (e.g. galex_patch.php)
/wp-content/plugins/Plugins you never installed — researchers observed a fake ~150 KB “CMSmap” plugin with obfuscated payloads
Database: wp_postscustomize_changeset or nav_menu_item rows dated exactly 2020-01-01 00:00:00
Database: wp_postmetaMeta values containing example.invalid
REST API routesAn unexpected /morning/v1/ endpoint accepting base64-encoded commands
Server access logsPOSTs to /wp-json/batch/v1; user agents wp2shell or rezwp2shell

Free scanners such as SOCRadar’s wp2shell checker only tell you whether your site is currently patched — they cannot tell you whether it was breached before you patched. If your site sat on a vulnerable version while exploits were circulating, work through the full cleanup below.

Before you clean anything: make a full backup

Back up all files and the complete database before you change anything. If a cleanup step goes wrong, the backup is your only way back — and a copy of the compromised state is useful evidence if you later need professional incident response. Work on a staging copy first if your host provides one.

Step 1: How to remove wp2shell files from your server

Start on the filesystem, because the webshells are what give attackers ongoing access. Connect over FTP or SSH and work through this list:

  1. Update WordPress core to 6.9.5 or 7.0.2 immediately. This closes the hole so attackers cannot re-enter while you clean.
  2. Delete webshells from cache folders. Inspect /wp-content/cache/ (and any other cache directories) and remove standalone PHP files with meaningless alphanumeric names.
  3. Check must-use plugins. Files in /wp-content/mu-plugins/ load automatically and cannot be deactivated from wp-admin, which makes the folder a favorite hiding spot. Delete anything you did not put there.
  4. Review installed plugins. Remove any plugin in /wp-content/plugins/ that you never installed.
  5. Verify core file integrity. A shell can also be appended to a legitimate core, theme, or plugin file. If you have WP-CLI, run wp core verify-checksums to compare every core file against the official release.

Then disable file editing from the dashboard. Add these two lines to wp-config.php, above the /* That's all, stop editing! */ comment:

define( 'DISALLOW_FILE_EDIT', true );
define( 'DISALLOW_FILE_MODS', true );

Caution: DISALLOW_FILE_MODS also blocks legitimate plugin and theme installs and updates from wp-admin. If your team updates plugins through the dashboard, keep only the first line and manage updates deliberately.

Step 2: How to reset passwords, keys, and sessions

Treat every credential as stolen. Attackers had database-level access, which very likely exposed password hashes — and post-exploitation activity observed by Wiz included user enumeration and authenticated wp-admin access.

  1. Reset all user passwords, administrators first. Change the MySQL database password too, and update it in wp-config.php.
  2. Log every device out. Generate fresh salt keys with the official WordPress secret-key generator and replace the old keys in wp-config.php. This invalidates every active session, including the attacker’s.
  3. Delete rogue administrators. In Users → All Users, filter by the Administrator role and remove any account you did not create.

Step 3: How to clean the WordPress database after wp2shell

The exploit seeded the database with fake customizer changesets and navigation menu items. These records typically carry the fixed date 2020-01-01 00:00:00 and payload URLs pointing to example.invalid. The queries below assume the default wp_ table prefix — change it if your site uses a custom prefix, and run them only after your database backup is done.

1. Delete spoofed changesets:

DELETE FROM wp_posts
WHERE post_type = 'customize_changeset'
  AND post_date = '2020-01-01 00:00:00';

2. Delete fake navigation menu items:

DELETE FROM wp_posts
WHERE post_type = 'nav_menu_item'
  AND post_date = '2020-01-01 00:00:00';

3. Delete malicious metadata:

DELETE FROM wp_postmeta
WHERE meta_value LIKE '%example.invalid%';

Step 4: How to harden WordPress against similar attacks

Three changes meaningfully reduce the blast radius of any future database-to-disk attack, and none of them affect normal WordPress operation.

  1. Revoke the MySQL FILE privilege. WordPress never needs it, and it is exactly what let wp2shell write PHP files to disk. Log in to MySQL as root and run the query below.
  2. Restrict the batch endpoint. If nothing on your site uses /wp-json/batch/v1, block or rate-limit it at your firewall or WAF — one of the mitigations recommended by Wiz.
  3. Keep automatic minor updates on. Sites with auto-updates enabled received 6.9.5 / 7.0.2 within hours of release on July 17, 2026, before mass exploitation began.
REVOKE FILE ON *.* FROM 'your_wp_db_user'@'localhost';
FLUSH PRIVILEGES;

For ongoing protection, see our comparison of WordPress security plugins, and if you are still on an older branch, our overview of what changed in WordPress 7.0.

This guide builds on a community cleanup walkthrough shared by u/codestormer on r/WordPress (July 2026), cross-checked against vulnerability research from Wiz, Rapid7, and The Hacker News.

Frequently asked questions

Is updating to WordPress 7.0.2 enough to remove wp2shell?

No. Updating to 6.9.5 or 7.0.2 closes the vulnerability but does not remove webshells, rogue admin accounts, or database records planted before you patched. A site exploited before the update stays compromised until you complete a full file, user, and database cleanup.

How do I check if my WordPress site was hacked through wp2shell?

Look for random-named PHP files in /wp-content/cache/, unknown files in /wp-content/mu-plugins/ (such as galex_patch.php), administrator accounts you did not create, database rows dated 2020-01-01 00:00:00, and POST requests to /wp-json/batch/v1 in your access logs.

Which WordPress versions are vulnerable to wp2shell?

WordPress 6.9.0–6.9.4 and 7.0.0–7.0.1 are vulnerable to the full remote-code-execution chain (CVE-2026-63030 + CVE-2026-60137). WordPress 6.8.0–6.8.5 is affected by the SQL injection alone. Versions 6.9.5 and 7.0.2, released July 17, 2026, are patched.

Do I need to change my passwords after wp2shell?

Yes. Attackers had database-level access, so assume password hashes were taken. Reset all WordPress user passwords, change the MySQL database password, and rotate the salt keys in wp-config.php to force every session to log out.

Does a firewall or security plugin protect against wp2shell?

A WAF rule blocking /wp-json/batch/v1 stops the known exploit chain, and several vendors shipped virtual patches. But no plugin or firewall replaces the core update — 6.9.5 / 7.0.2 is the only complete fix.

← Previous Post
Next Post →