Hackers are actively exploiting a two-part critical flaw suite nicknamed "wp2shell" — CVE-2026-63030 and CVE-2026-60137 — in WordPress Core to deploy persistent PHP webshells and malicious plugins on affected servers without authentication. The chain abuses the WordPress REST API's batch-processing feature together with a WP_Query SQL injection to reach pre-authentication remote code execution on default installations. WordPress has shipped fixes in versions 7.0.2, 6.9.5, and 6.8.6 and pushed automatic security updates to supported installations, yet proof-of-concept exploits surfaced over the weekend and multiple vendors have now confirmed in-the-wild attacks.

Inside the wp2shell chain

The vulnerability suite pairs two bugs that work together. CVE-2026-63030 is a REST API "batch route confusion" issue at the batch endpoint /wp-json/batch/v1 (or /?rest_route=/batch/v1). The endpoint processes sub-requests in two phases: it first matches each path to a handler, then dispatches each request through its matched handler. When a deliberately malformed path (///) is inserted as the first sub-request, WordPress stores a WP_Error at index 0 of the matched-routes array, which shifts every subsequent handler assignment back by one index. The dispatch loop then pairs each request with the wrong handler — a request validated against Schema A is executed by Handler B, bypassing the parameter sanitization that Schema A enforced.

CVE-2026-60137 is an SQL injection in WP_Query. The posts collection endpoint accepts an author_exclude parameter whose schema enforces integer-typed array values, sanitizing each element with absint() before it reaches WP_Query. The batch desync causes this parameter to bypass schema validation entirely and arrive at WP_Query's author__not_in logic as a raw string. Because absint() is only applied inside an is_array() branch, the raw string is interpolated directly into the SQL WHERE clause, enabling UNION SELECT injection.

WordPress 6.9.0 through 6.9.4 and 7.0.0 through 7.0.1 are vulnerable; the issue is fixed in 6.9.5 and 7.0.2, and the disclosure timeline also lists 6.8.6 as a patched branch. The chain was discovered by Adam Kues of Assetnote and SearchLight Cyber and disclosed on 2026-07-17, with advisories GHSA-ff9f-jf42-662q and GHSA-fpp7-x2x2-2mjf. NVD's entry for CVE-2026-63030 confirms that the batch route confusion, combined with the author__not_in SQL injection, can allow SQL injection and remote code execution.

What attackers are doing in the wild

Cloud security company Wiz published technical details on observed attacks, reporting activity that includes:

  • Mass-scanning for vulnerable WordPress installations (much of it routine security scanning).
  • Abuse of WordPress plugin upload functionality to install malicious add-ons.
  • Installation of PHP webshells ranging from simple one-liner backdoors to feature-rich, obfuscated shells disguised as plugins (CMSmap).
  • Querying the WordPress REST API to collect administrator usernames and email addresses.
  • Local file inclusion attempts targeting wp-config through admin-ajax.php to retrieve database credentials and authentication keys.
  • Deployment of a malicious plugin exposing a REST API endpoint for remote command execution.
  • Successful access to WordPress administration panels.

Wiz says it has not observed lateral movement or data exfiltration but continues to monitor the threat. A separate report from Johannes B. Ullrich, Dean of Research at the Sans Technology Institute, describes two-stage attacks that begin with probing SQL injection to confirm the vulnerability before delivering a PHP webshell to the server. The webshell was created under the /wp-content/cache/ directory with a randomized filename that also served as the password, supplied via a variable in a URL request; otherwise the page returned a fake 404 page. Ullrich's published webshell code checked the availability of system(), passthru(), exec(), shell_exec(), popen(), and the backtick operator to run commands. Some attacks also create rogue administrator accounts, so the researcher recommends auditing the /cache/ directory and looking for newly created users.

WordPress security firm Defiant posted an "aftermath" analysis stating that the first exploitation-related probing was observed at 23:29 UTC on July 17, followed by a clear SQL injection attempt just 13 minutes later.

Proof of concept

The public PoC landscape moved quickly after disclosure. Researcher 0xsha's wp2shell repository consolidates the work, and its README describes the chain verbatim:

REST API batch route confusion (CVE-2026-63030) chained with a WP_Query author__not_in SQL injection (CVE-2026-60137) → pre-auth remote code execution against a default WordPress install.

Discovered by Adam Kues (Assetnote / Searchlight Cyber), disclosed 2026-07-17. Advisories: GHSA-ff9f-jf42-662q , GHSA-fpp7-x2x2-2mjf .

The repo ships wp2shell.py, an original stdlib-only tool that unifies the best of six public PoCs into a single file, with no requests dependency and no broken features:


wp2shell/
├── README.md              ← you are here
├── wp2shell.py            ← the unified PoC (single file, stdlib only, by 0xsha)
└── lab/

Its documented capabilities include the full crack-free RCE, verified end-to-end in-lab: a shell with no credentials forges a fake WP_Post via the single-post UNION confusion, bridges the customizer to create a fresh administrator (POST /wp/v2/users), logs in, and drops a token-gated webshell. The SQLi admin-hash dump (read --preset users) is kept as a second, verified path. It also provides a version-independent confusion detector (block_cannot_read) as the primary non-destructive check, production transport on every command (self-signed TLS, custom headers, custom User-Agent, proxy, retries, request delay), a verified 6.8.x facilitated-SQLi path (sqli), reproducible Docker labs plus a version-by-DB reliability matrix with every result verified in-lab, and a hashcat mode for the new $wp$2y$ password hash (-m 35500).

A second repository, c0gnit00/Wp2Shell, documents the same pre-authentication RCE in WordPress Core, explicitly flagged for educational and authorized security research purposes only. Its walkthrough lays out the early exploitation steps:

  • Confirm the batch endpoint is reachable and the desync is functioning.
  • Extract the database version, user, table prefix, and administrator credentials via UNION SELECT rows reflected in the REST JSON response.

Detection and mitigation

Administrators of WordPress sites should immediately update to the patched versions (7.0.2, 6.9.5, or 6.8.6), review logs for wp2shell-related requests, inspect installed plugins, and check for rogue PHP file additions or newly created admin accounts. Monitoring the patch rate may help prioritize response: Macnica researcher Yutaka Sejiyama has built a live dashboard that reports an 81.6% patch rate out of a sample of 124,580 websites evaluated.

The checks below are generic examples for illustration, not vendor-published IoC lists for this incident:


# Look for batch-route desync and author_exclude traffic in access logs (generic pattern)
grep -E 'rest_route=%2Fbatch%2Fv1|author_exclude' /var/log/nginx/access.log*

# Hunt for recently dropped PHP files under the cache directory
find wp-content/cache -name '*.php' -newermt '2026-07-17' -ls

# Scan for common webshell markers
grep -RIl 'eval(\|base64_decode(\|shell_exec(\|assert(' wp-content/ 2>/dev/null

# List administrators to spot rogue accounts
wp user list --role=administrator --fields=ID,user_login,user_registered

SearchLight Cyber researcher Adam Kues has also published a follow-up report detailing the process of discovering wp2shell and developing a working exploit chain, which involved the use of AI tools.

References