
Nicht-destruktiver Detektor für CVE-2026-64638 (XSS2Shell) — WordPress Pre-Auth-XSS-Reflexions-Primitiv
Nicht-destruktiver Detektor ohne Abhängigkeiten für das Reflection-Primitive CVE-2026-64638 („XSS2Shell") in WordPress wp-login.php.
CVE-2026-64638 ist eine vor der Authentifizierung ausnutzbare, reflektierte XSS-Schwachstelle im WordPress-Core, die von PWN.AI am 07.08.2026 offengelegt wurde (CVSS 8.9, CWE-79) und in 7.0.3 gepatcht wurde, mit Backports für alle gepflegten Branches (6.9.6, 6.8.7, 6.7.6, 6.6.6, 6.5.9, …).
Die Ursache ist eine Parser-Differenz zwischen strip_tags() in PHP und dem KSES-Sanitizer von WordPress:
strip_tags() weigert sich, ein Tag zu erkennen, wenn auf < ein Leerzeichen folgt, sodass ein Benutzername wie < area id=x> als Klartext überlebt.<area id="x">-Element innerhalb der Login-Fehlermeldung.Das ergibt eine vom Angreifer wählbare DOM-Injection mit wählbaren id-/class-/href-Attributen — das Primitive hinter der veröffentlichten mehrstufigen Kette (DOM-Clobbering → REST-JSONP → Diebstahl von Anwendungspasswörtern → Plugin-Upload → RCE gegen ein eingeloggtes Admin-Opfer).
Zwei nicht-destruktive Sonden (ein fehlgeschlagener Login mit einem zufälligen Marker-Benutzernamen):
<b>marker</b> erscheint unmaskiert in der Fehlerantwort.< area id=marker> übersteht strip_tags() und erscheint erneut als lebendes/normalisiertes Element (z. B. area id="marker") in der Antwort.Kein Payload führt etwas aus; das Tool misst lediglich, ob Angreifer-HTML als lebendes DOM gerendert wird. Optionale Extras:
--version — Fingerprinting der Core-Version über das Feed-<generator>-Tag.--jsonp — prüft, ob das in der veröffentlichten Kette verwendete REST-JSONP-Envelope (_jsonp/_envelope) erreichbar ist.python3 xss2shell_check.py https://example.com
python3 xss2shell_check.py --jsonp --verbose https://example.com
python3 xss2shell_check.py --version https://example.com
python3 xss2shell_check.py --json https://example.com
Python 3.6+, nur Standardbibliothek. Keine Abhängigkeiten.
| Code | Bedeutung |
|---|---|
| 0 | VERWUNDBAR (Reflection-Primitive vorhanden) |
| 1 | GEPATCHT / NICHT VERWUNDBAR |
| 2 | FEHLER (nicht erreichbar, WAF-Challenge, unerwartete Antwort) |
<area id="…">). Die Anführungszeichen bei Attributen variieren je nach KSES-Generation (alter Custom-Parser: <area id=x>; DOMDocument: <area id="x"> / <area id="x" />), daher werden alle Formen abgeglichen. Ein rohes < area …>-Durchreichen ohne erneutes Parsen ist im Browser nur inaktiver Text, nicht das Primitive — es wird als RAW_TEXT_ONLY gemeldet und löst keinen False Positive aus.login_errors-Filter oder CDN/WAF Antworten umschreibt oder die Login-Fehlermeldung den Benutzernamen nie zurückspiegelt.Nur für autorisierte Sicherheitstests. Dieses Tool ist ausschließlich für Tests an Systemen bestimmt, die dir gehören oder für die du eine ausdrückliche schriftliche Genehmigung zur Bewertung hast. Nicht autorisierte Tests sind in den meisten Rechtsordnungen illegal.
| Flag | Zweck |
|---|
--version | Fingerprinting der Core-Version (Feed-Generator-Tag, Homepage-Meta als Fallback) |
--jsonp | zusätzlich prüfen, ob das REST-JSONP-Envelope (_jsonp/_envelope) erreichbar ist |
-v, --verbose | Antwortausschnitte der Sonden ausgeben (Belege für Berichte) |
--json | maschinenlesbares JSON-Ergebnis (CI/Automatisierung) |
| Beobachtetes Verhalten | Befund | Exit |
|---|
<b>marker</b> unmaskiert zurückgegeben | RAW_HTML — verwundbar | 0 |
< area id=marker> wird erneut zu einem lebenden <area id="marker"> geparst (beliebige Anführungszeichen/Void-Form) | AREA_BYPASS — verwundbar | 0 |
| Benutzername HTML-maskiert | ESCAPED — nicht verwundbar | 1 |
| Tags entfernt, Text bleibt | STRIPPED — nicht verwundbar | 1 |
Rohes < area …> wird durchgereicht, aber nie erneut geparst | RAW_TEXT_ONLY — inaktiver Text, nicht verwundbar | 1 |
| Keine Zurückspiegelung | NOT_REFLECTED — nicht verwundbar | 1 |
| Sonde blockiert (HTTP ≥ 400 / Challenge-Seite) oder Ziel nicht erreichbar | FEHLER | 2 |