July 18, 2026
wp2shell: Breaking Down the Critical WordPress RCE (CVE-2026–60137 + CVE-2026–63030)
Hi Guyz
By ஜெய்
1 min read
On July 17, 2026, a critical pre-authentication RCE in WordPress Core was disclosed. No plugins required. No authentication needed. Just a stock WordPress install on versions 6.9.0–6.9.4 and 7.0.0–7.0.1.
Two Bugs, One Chain
This isn't a single vulnerability — it's a chain of two:
CVE-2026–60137 — SQL injection in the author__not_in parameter of WP_Query. Discovered by TF1T, dtro, and haongo. Alone, it's rated Moderate because it requires authentication to reach.
CVE-2026–63030 — REST API batch-route confusion. Discovered by Adam Kues at Assetnote / Searchlight Cyber. This is the key that unlocks the door — it allows unauthenticated attackers to reach the SQLi through the batch API.
Combine them, and you get Critical RCE.
Affected Versions
<= 6.8.5 — Not affected (no batch confusion) 6.9.0–6.9.4 — Vulnerable 7.0.0–7.0.1 — Vulnerable 7.0.2+ — Patched
How the Exploit Works
The attack chain is complex but elegant:
-
Batch-route confusion — The batch API (/batch/v1) is tricked into processing requests out of order, bypassing authentication checks.
-
Time-based blind SQLi — The author_exclude parameter (which maps to author__not_in) is injected with a SLEEP()-based timing oracle. Each bit of data is extracted one character at a time through binary search.
-
oEmbed cache corruption — The SQLi is used to inject fake oEmbed cache entries into the database via UNION injection. These entries are crafted to look like WordPress customizer changesets.
-
Admin account creation — The forged changeset publishes with admin authorship privileges, creating a new administrator account.
-
Plugin upload + RCE — With admin access, a malicious plugin is uploaded that registers a REST API command execution endpoint. The command runs, output is returned, and the plugin self-destructs.
The Speed Problem
This is a time-based blind SQLi — it's inherently slow. Each character of extracted data requires ~7 HTTP requests, each with a SLEEP(0.4) on successful conditions. The full chain takes ~35–70 seconds depending on network latency.
You can't speed this up without changing the technique. Error-based or UNION-based extraction would be instant, but the injection point here doesn't return visible output — only timing tells you if a condition was true or false.
Mitigation
Update to WordPress 7.0.2, 6.9.5, or 6.8.6 immediately. If you can't update, block access to /wp-json/batch/v1 and /?rest_route=/batch/v1 at your WAF.
The Script
A working PoC is available at https://github.com/h4cd0c/wp2shell. Use it responsibly — only against targets you own or have explicit permission to test.