
Analyse und End-to-End-Implementierung der gepatchten wordpress RCE-Sicherheitslücke - CVE-2026-60137 und CVE-2026-63030

Alle PoCs nutzen dieselben zwei Schwachstellen – die REST-Batch-Routen-Verwirrung (CVE-2026-63030) und die
author__not_in SQL-Injection (CVE-2026-60137) – mit derselben doppelt verschachtelten Batch-Struktur.
Was sie unterscheidet, ist der gewählte RCE-Pfad, die Umgebungsvoraussetzungen
und die Sicherheitsstandards. Dieses Dokument beschreibt konkret, wo die Implementierung in
diesem Repository in dieser Landschaft steht.
check sendet ohne explizite Aufforderung keine SQL-Nutzlast;
der gesamte Datenverkehr kann ein Attributions-Tag tragen; alles, was der shell-Befehl auf das Ziel schreibt,
wird danach automatisch entfernt. Siehe §3.| Fähigkeit | Dieses Repository | Icex0/wp2shell-poc | sergiointel/wp2shell-poc | 0xsha/wp2shell | OUTFILE-Variante [4] |
|---|---|---|---|---|---|
| Pre-Auth-Blind-/Timing-SQLi-Auslesen | ja | ja | ja (Timing) | ja | ja |
| In-Band-UNION-Auslesen (1 Anfrage/Wert) | ja | ja | - [1] | - [1] | - |
| Fehlerbasiertes Auslesen (EXTRACTVALUE) | ja | ja | - | - | - |
| UNION-Kanal überlebt persistenten Objekt-Cache | ja (geleerte Basis) | nein – Probe false-negatives [2] | nicht dokumentiert | nein – dokumentierte Voraussetzung [3] | n/a [5] |
| Crack-freie Pre-Auth-RCE | ja (SQLi-zu-Admin-Brücke) | ja (gleiche Brücke) | ja (Ursprung der Brücke) | ja (gleiche Brücke) | ja, via INTO OUTFILE [5] |
| Zusätzliche Voraussetzungen für RCE | keine über Standardinstallation hinaus | keine (auf Hosts ohne Objekt-Cache) | keine (gleich) | keine (gleich) | MySQL FILE-Privileg + von mysqld beschreibbarer und vom Webserver auslieferbarer Pfad |
| Zerstörungsfreie Überprüfung / Patch-Validierung | ja (Marker-Triplett; standardmäßig keine Nutzlast) | ja | nein | ja (block_cannot_read) | ja (Marker-Batch) |
| Attributions-/User-Agent-Tagging | ja, bei allen Befehlen | nein | nein | Transport-Flag | nein |
| Automatische Bereinigung (Webshell + erstellter Admin) | ja | ja | nicht dokumentiert | nur token-gesteuerte Webshell | Dropper entfernt [5] |
| Leitfaden zur Erkennung für Blue Teams | ja, aus einem Produktionseinsatz | nein | nein | stattdessen Labor-Matrix | Hinweise zur Eindämmung |
| Abhängigkeiten | nur Standardbibliothek | nur Standardbibliothek | einzelne Datei | nur Standardbibliothek, einzelne Datei | Python ≥3.10 Paket |
[1] Nur Timing/Blind als Auslesekanal; das UNION-Fake-Post-Primitiv existiert innerhalb der
Brücke, wird aber nicht als Extraktions-Orakel bereitgestellt.
[2] Der naive Verfügbarkeitstest (0) UNION SELECT …) wird während der Objekt-Cache-
Hydrierung stillschweigend verworfen, available() gibt false zurück und die gesamte Pre-Auth-Brücke
wird abgebrochen – siehe §1.
[3] Das eigene README des Projekts listet „kein persistenter Objekt-Cache (Redis/Memcached)“ unter
Voraussetzungen.
[4] Öffentliche Variante, gespiegelt bei Sploitus (Link unten): Blind-Auslesen plus ein INTO OUTFILE
Dropper als RCE-Schritt, unter Verwendung eines per_page=-1 categories-Trägers.
[5] Der OUTFILE-RCE-Pfad hängt nicht vom Rendern von Fake-Posts ab, daher blockieren Objekt-Caches
ihn nicht – das MySQL FILE-Privileg und ein gemeinsamer beschreibbarer Pfad tun dies. Managed Hosting
gewährt dem WordPress-DB-Benutzer fast nie FILE, und secure_file_priv ist häufig gesetzt.
Das UNION-Fake-Post-Primitiv hängt davon ab, wie WP_Query Zeilen zurückgibt:
wp_posts-Zeilen zurück; eine durch UNION
injizierte Zeile wird direkt zu einem WP_Post. Die Fälschung wird gerendert.Auf Hosts mit einem persistenten Objekt-Cache drückt ein befüllter Basisergebnissatz WP_Query in den
geteilten Modus. Der Standardtest der öffentlichen PoCs –
0) UNION SELECT <gefälschte Zeile> -- -
– lässt den Basissatz befüllt (post_author NOT IN (0) trifft auf jede Zeile zu), sodass die
gefälschte Zeile hinter einem Objekt-Cache verdampft: der Verfügbarkeitstest wird zum False-Negative,
available() gibt false zurück, und die gesamte Pre-Auth-Brücke wird auf einem Host als „tot“ gemeldet,
der tatsächlich voll ausnutzbar ist. Der öffentliche Unifier dokumentiert dieselbe Grenze, indem er
„kein persistenter Objekt-Cache“ als harte Voraussetzung auflistet.
Dieses Repository leert stattdessen den Basissatz:
1) AND 1=0 UNION ALL SELECT <gefälschte Zeile> -- -
Ohne Basiszeilen ist die gefälschte Zeile die einzige Zeile; die Abfrage bleibt im Vollzeilen-Modus;
keine Hydrierungsabfrage wird jemals ausgeführt. Ein einziges injiziertes Schlüsselwort (AND 1=0) ist der
gesamte Unterschied zwischen „UNION-Kanal tot“ und „vollständige Pre-Auth-RCE“ auf gehosteten Objekt-Caches –
was die Mehrheit der verwalteten WordPress-Produktionsumgebungen sind. Die Diagnose, die Test-Matrix
(per_page × Injektionsform).
Hinweis zum Umfang: der Blind-/Timing-Auslesekanal ist nicht objekt-cache-sensitiv (Zeilen zählen in SQL beinhaltet keine Fake-Post-Hydrierung), daher funktioniert das Blind-Auslesen jedes PoCs überall. Was der Objekt-Cache in den anderen PoCs tötet, ist speziell der UNION-abhängige Teil: In-Band-Extraktion und die SQLi-zu-Admin-Brücke.
Eine zweite, verwandte Lektion, die in der Fallstudie dokumentiert ist: wenn beide Kanäle funktionieren, behandle das In-Band-UNION-Auslesen als autoritativ – das Produktions-Timing-Orakel produzierte Bit-Flips unter Jitter für einen Wert, den das In-Band-Auslesen eindeutig feststellte.
Drei Pre-Auth-RCE-Pfade existieren in den öffentlichen PoCs:
| Pfad | Verwendet von | Zusätzliche Voraussetzungen |
|---|---|---|
SQLi-zu-Admin-Brücke (fälsche oEmbed/Changeset/Nav-Zeilen → POST /wp/v2/users → Login → Plugin-Upload) | dieses Repository, sergiointel (Ursprung), Icex0, 0xsha | keine über eine Standardinstallation hinaus |
INTO OUTFILE-Dropper (schreibt eine PHP-Datei via SQLi, ruft sie für eine Shell ab) | OUTFILE-Variante [4] | MySQL FILE-Privileg, secure_file_priv erlaubt es, und ein Verzeichnis, das von mysqld beschreibbar und vom Webserver ausgeliefert wird |
Hash-Wiederherstellung → Crack → Login (dump user_pass, offline cracken, dann Plugin-Upload) | alle (als Fallback) | der bcrypt-Hash muss tatsächlich gecrackt werden ($wp$2y$, hashcat -m 35500) – langsam, oft nie |