Share
## https://sploitus.com/exploit?id=79AB6349-D374-5051-B29D-10681E537E39
# CVE-2026-63030 / CVE-2026-60137 โ€” "wp2shell" WordPress Core RCE Chain

**Discoverer:** Searchlight Cyber (via GPT-5.6 Sol)  
**Severity:** Critical โ€” CVSS 9.8 (CVE-2026-63030), CVSS 9.1 (CVE-2026-60137)  
**Status:** Actively exploited โ€” added to CISA KEV  
**Alias:** "wp2shell"

---

## Overview

This is an unauthenticated remote code execution chain in WordPress Core composed of two CVEs:

| CVE | Component | Type | CWE |
|---|---|---|---|
| CVE-2026-63030 | WP REST API batch endpoint | Route confusion / access-control bypass | CWE-436 |
| CVE-2026-60137 | `WP_Query` `author__not_in` parameter | SQL injection | CWE-89 |

Individually each flaw is serious; combined they allow an unauthenticated attacker to execute arbitrary PHP on the target and deploy webshells.

---

## Technical Details

### CVE-2026-63030 โ€” Batch Endpoint Route Confusion

The WordPress REST API exposes a batch endpoint at `/wp-json/wp/v2/batch`. Due to a flaw in route resolution (introduced in WP 6.9's rewritten routing middleware), the batch processor does not correctly validate that *internal* sub-requests in a batch inherit the authentication and permission checks of the outer request. An attacker can craft a batch payload that:

1. Escapes the route namespace boundary.
2. Invokes privileged endpoints (e.g. `wp/v2/users`, `wp/v2/plugins`) without the required capability checks.
3. Leverages `WP_REST_Server::dispatch()` to pass forged route parameters to internal handlers.

This bypasses all authentication guards for *read* operations and some *write* operations when combined with parameter smuggling.

### CVE-2026-60137 โ€” `author__not_in` SQL Injection

The `WP_Query` class accepts an `author__not_in` parameter intended to exclude posts by specific author IDs. A type-coercion bug in the `WP_Query::get_posts()` method (introduced in WP 6.9's query sanitization refactor) causes `author__not_in` values to be interpolated directly into the SQL `WHERE` clause without proper parameterisation when supplied as a specially crafted associative array.

The injection occurs in the `post_author IN (...)` generated SQL. By nesting arrays with raw SQL fragments an attacker can break out of the `IN` clause and execute arbitrary `UNION` / `INTO OUTFILE` statements โ€” provided the database user has `FILE` privilege.

### Combined Chain

```
Attacker (unauthenticated)
  โ”‚
  โ”œโ”€ POST /wp-json/wp/v2/batch
  โ”‚    โ””โ”€ CVE-2026-63030: Bypass auth, invoke internal query API
  โ”‚         โ””โ”€ CVE-2026-60137: Inject SQL via author__not_in
  โ”‚              โ””โ”€ UNION SELECT ... INTO OUTFILE 'webshell.php'
  โ”‚                   โ””โ”€ Webshell deployed to web root
  โ”‚                        โ””โ”€ RCE achieved
```

The batch endpoint provides the *vector*; the SQLi provides the *payload delivery*.

---

## Affected Versions

| Version range | Full chain |
|---|---|
| WordPress 6.9.0 โ€“ 6.9.4 | โœ… Both CVEs present |
| WordPress 7.0.0 โ€“ 7.0.1 | โœ… Both CVEs present |
| WordPress โ‰ค 6.8.x | CVE-2026-63030 only (SQLi not exploitable) |

Patches were shipped in WordPress 6.9.5 and 7.0.2 (both issued 2026-07-16).

---

## Reproduction Steps

1. Confirm target WordPress version is in the affected range.
2. Verify `/wp-json/wp/v2/batch` returns 200 (not 403/404).
3. Run the PoC with the `--target` flag (see below).
4. Confirm webshell at `/wp-content/webshell.php?cmd=id`.

---

## PoC Usage

```
python exploit.py --target https://target.example.com --action deploy-webshell
python exploit.py --target https://target.example.com --action exec --command "id"
python exploit.py --target https://target.example.com --action exec --command "uname -a"
```

---

## Mitigation

- **Upgrade** to WordPress 6.9.5+ or 7.0.2+.
- If immediate patching is impossible:
  - Block `POST /wp-json/wp/v2/batch` at the WAF / reverse proxy.
  - Remove `FILE` privilege from the WordPress MySQL user.
  - Enable `define('DISALLOW_FILE_EDIT', true);` and `define('DISALLOW_FILE_MODS', true);`.
- Monitor for unexpected `.php` files under `wp-content/`.
- Check for `author__not_in` with non-integer values in request logs.

---

## References

- [Searchlight Cyber Advisory โ€” "wp2shell"] (https://searchlightcyber.com/advisories/wp2shell)
- [CVE-2026-63030 โ€” NVD](https://nvd.nist.gov/vuln/detail/CVE-2026-63030)
- [CVE-2026-60137 โ€” NVD](https://nvd.nist.gov/vuln/detail/CVE-2026-60137)
- [CISA Known Exploited Vulnerabilities Catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)
- [WordPress Core 6.9.5 Release Notes](https://wordpress.org/news/2026/07/wordpress-6-9-5/)