~/blog/second-pass-three-blind-spotsPOSTED
von Shady Nathan Tawfik · 5. Oktober 2026 · 6 min

Der zweite Durchgang: Drei blinde Flecken, die ein gehärteter WordPress-Audit übersah

Der erste Durchgang nannte die Seite gehärtet und bewertete sie mit HOCH. Der zweite, tiefere Durchgang fand eine aktiv ausgenutzte WordPress-Core-RCE, eine CORS-Reflexion mit Credentials auf der REST-API und drei installierte, aber unsichtbare Plugins — und machte daraus KRITISCH.

Interaktiv[blog-2.0]

TL;DR: Mein erster Durchgang nannte die Seite gehärtet und bewertete sie mit HOCH. Der zweite Durchgang fand eine unauthentifizierte WordPress-Core-RCE, die bereits im CISA-KEV-Katalog stand, eine CORS-Reflexion mit Credentials, die ich an der falschen URL getestet hatte, und drei Plugins, die nie im HTML auftauchten. Gleiche Oberfläche, andere Fragen, anderes Urteil: KRITISCH.

Die Ausgangslage

Ich hatte diese Seite schon einmal auditiert. Das Fazit war beruhigend: Login und Admin hinter Basic Auth, die REST-User-Endpoints geschlossen, xmlrpc zu, Kommentare deaktiviert. Für eine WordPress-Installation ist das überdurchschnittlich, und der Bericht sagte das auch.

Dann bat mich der Auftraggeber, so tief wie möglich zu graben. Kein neuer Zugang, keine neue Technik. Ich startete auf derselben öffentlichen Oberfläche und stellte andere Fragen. Das Ergebnis war keine Ergänzung des ersten Berichts. Es war eine Korrektur.

Ich habe alle identifizierenden Informationen entfernt. Das Ziel wird nur nach Branche und Technologieklasse beschrieben, damit das Muster wiederverwendbar bleibt.

Das Muster

Ein Rescan ist nicht "den ersten Scan nochmal laufen lassen". Es ist eine andere Checkliste. Drei blinde Flecken machten aus demselben Ziel ein HOCH — und dann ein KRITISCH.

Blinder Fleck 1: Die Version galt als "aktuell genug"

Der erste Durchgang notierte die Core-Version und ging weiter, weil damals nichts dazu passte. Der zweite Durchgang map-te die exakte Version gegen die seither veröffentlichten Advisories — und fand einen Path Traversal in der Page-Template-Auflösung mit bedingter RCE. Der Eintrag stand im CISA-KEV-Katalog und wurde Stunden nach der Veröffentlichung massenhaft ausgenutzt. Die Ziel-Version lag im betroffenen Bereich, und das Theme-Verzeichnis erfüllt die dokumentierte erste Vorbedingung.

Die Lehre ist nicht "Version prüfen". Sondern: die Version gegen den Advisory-Stand zum Audit-Zeitpunkt mappen — und verstehen, dass eine Härtungs-Checkliste eine Core-Lücke nicht abdeckt.

Blinder Fleck 2: CORS wurde an der falschen URL getestet

Mein erster Durchgang testete Cross-Origin-Header auf der Startseite und fand nichts. Das ist bei WordPress ein naheliegender, aber falscher Test. Die REST-API unter /wp-json/ ist der entscheidende Endpoint, und die Fallback-Form ?rest_route= muss separat geprüft werden. Beide reflektierten einen beliebigen Origin zusammen mit Access-Control-Allow-Credentials: true — eine Kombination, die jeder Website, die ein eingeloggter Nutzer besucht, credentialisierte Cross-Origin-Aufrufe erlaubt. Der WordPress-Nonce reduziert den praktischen Impact, aber die Fehlkonfiguration ist real — und von der Startseite aus unsichtbar.

Blinder Fleck 3: Das Inventar kam aus dem HTML

Das Fingerprinting im HTML ergab sieben Plugins — das, was die Seite preisgab. Der zweite Durchgang verglich existierende Plugin-Verzeichnisse mit einer Nicht-Existenz-Baseline: ein fehlendes Plugin liefert die 404-Seite der Website, ein existierendes eine Verzeichnis-Antwort. Dieses Differential förderte drei weitere Plugins zutage: ein Sharing-Plugin mit offenem Stored-XSS-Advisory, ein Custom-Fields-Plugin mit zwei offenen Advisories und ein Premium-Caching-Plugin, dessen Version extern nicht bestimmbar war. Genauso wichtig war das Fehlende: kein Backup-Plugin, kein Security-Plugin, kein Aktivitätsprotokoll. Eine Kompromittierung hinterließe hier keine wiederherstellbare Kopie und keine Spur.

TL;DR: Mein erster Durchgang nannte die Seite gehärtet und bewertete sie mit HOCH. Der zweite Durchgang fand eine aktiv ausgenutzte WordPress-Core-RCE, eine CORS-Reflexion mit Credentials auf der REST-API und drei installierte, aber unsichtbare Plugins — und machte daraus KRITISCH.

Befunde

SchwereBefundNachweis
KRITISCHUnauthentifizierter Core-Path-Traversal, bedingte RCE, in CISA KEVVersion im betroffenen Bereich; Theme-Vorbedingung aus der öffentlichen Body-Class beweisbar
KRITISCHCORS-Reflexion mit Credentials auf der REST-APIJeder Origin reflektiert mit Access-Control-Allow-Credentials: true auf /wp-json/ und ?rest_route=
HOCHDrei Schwester-Domains ohne DMARC und mit Softfail-SPFMandanten-Phishing ganz ohne Ausnutzung möglich
HOCHTheme liefert jQuery von 2012 und überschreibt die aktuelle Core-VersionBekannte XSS- und Prototype-Pollution-Advisories; Konsolenwarnung in Produktion
MITTELDrei versteckte Plugins mit offenen CVEsSharing-, Custom-Fields- und Caching-Plugin nur per Verzeichnis-Differential gefunden
MITTELKein Backup-, Security- oder Audit-Plugin installiertBei Ausnutzung der RCE weder Wiederherstellung noch Detektion
MITTELUndeklariertes Calltracking über den Tag Manager geladenEin Cookie, das die Datenschutzerklärung nicht nennt
MITTELKein HSTS, keine CORS-Allow-List, keine Security-Header auf der HauptflächeBasic-Auth-Credentials in feindlichen Netzen downgradebar
NIEDRIGFTP offen, Banner nennt den BetreiberInfrastruktur-Admin offengelegt; Brute-Force-Fläche

Der Angriffspfad

Public scan finds WordPress 6.8.3Map version against current advisoriesUnauthenticated path traversal in the change logTheme body class proves the page directory preconditionProbe the PEAR constellation on the serverInclude a local PHP file and drop a webshellRead wp-config and export the client database

Reproduktion im Labor

Jeder Befehl unten zielt auf einen Lab-Container, den ich selbst kontrolliere. Nichts davon ist auf ein laufendes System gerichtet.

~/code/bash bash
# 1. Version und Theme-Vorbedingung (Lab-WordPress 6.8.3 mit page-Template-Ordner)
curl -s http://lab.local/ | grep -E 'generator|body class'
# <- generator 6.8.3, Body-Class enthält page-template-page-templates

# 2. CORS-Differential: Startseite vs. API-Wurzel vs. Fallback
curl -s -D - -o /dev/null -H 'Origin: https://evil.example' http://lab.local/
curl -s -D - -o /dev/null -H 'Origin: https://evil.example' http://lab.local/wp-json/
curl -s -D - -o /dev/null -H 'Origin: https://evil.example' 'http://lab.local/?rest_route=/'
# <- die API-Antworten tragen Access-Control-Allow-Origin: https://evil.example

# 3. Versteckte Plugins per Differential
curl -s -o /dev/null -w '%{http_code} %{size_download}\n' http://lab.local/wp-content/plugins/gibt-es-nicht/
curl -s -o /dev/null -w '%{http_code} %{size_download}\n' http://lab.local/wp-content/plugins/sharing-plugin/
# <- 404 mit der Site-Seite vs. 403 mit leerem Apache-Body

Erkennung im eigenen Bestand

  • Jede Core- und Plugin-Version gegen den Advisory-Stand des Audit-Datums mappen, nicht gegen "wir haben kürzlich aktualisiert". Ein CISA-KEV-Eintrag ändert die Priorität sofort.
  • CORS auf /wp-json/ und ?rest_route= prüfen, nie nur auf der Startseite.
  • Das Verzeichnis-Differential auf den eigenen Plugin-Ordner anwenden und mit dem geglaubten Inventar vergleichen.
  • Die Fehlliste explizit prüfen: Backup-, Security- und Audit-Log-Plugins. Fehlende Resilienz ist ein Befund.
  • Jedes externe Skript gegen eine Allow-List prüfen und Subresource Integrity verlangen, wo der Anbieter es unterstützt; die Supply-Chain-Kampagnen 2026 kamen über Update-Server und CDNs, nicht über Code.

Behebung

~/code/text text
# innerhalb von 24 Stunden
1. Core auf den gepatchten Release des betroffenen Zweigs aktualisieren
2. CORS: Reflexion durch feste Allow-List ersetzen, niemals mit Credentials
3. DMARC für jede Domain des Portfolios, nicht nur für die Hauptdomain
4. Datenbank-Konsole gaten (VPN oder IP-Allowlist, Auth, Rate-Limit)

# innerhalb einer Woche
5. jedes Plugin auf den aktuellen Release heben; Premium-Plugins manuell prüfen
6. Theme-jQuery durch Core-jQuery ersetzen und die Theme-Skripte fixen
7. Header-Baseline und HSTS auf jedem Vhost ausliefern
8. Backup-, Security-Monitoring- und Activity-Log-Plugins installieren

# innerhalb eines Monats
9. Credentials und Salts nach dem Core-Update rotieren
10. beide externen Agenturen per AVV und MFA binden, Patch-SLA festschreiben

Sobald ein Angreifer Zugriff hat, kann er folgende Aktionen durchführen:

Unauthentifizierte RCE über den Core-Path-Traversal (CISA KEV)
CORS mit Credentials: jede besuchte Website liest die REST-API
Spoofbare Schwester-Domains: Mandanten-Phishing ganz ohne Exploit
Versteckte Plugins (Shariff, ACF, WP Rocket) mit offenen CVEs
Kein Backup-, Security- oder Audit-Plugin: keine Recovery, keine Detektion

Fazit — was ich daraus mitnehme

  • Ein gehärteter Perimeter ist kein sicherer Kern. Basic Auth schützt den Login, nicht die Version.
  • Den Endpoint testen, der zählt. Bei WordPress liegt CORS an der API-Wurzel, nicht auf der Startseite.
  • Ein Inventar aus dem HTML ist eine Marketing-Liste, keine Asset-Liste. Ein Differential nutzen.
  • Nach dem Fehlenden fragen. Kein Backup und kein Log auf einer Seite mit Mandantendaten ist selbst ein Risiko.
  • Ein Rescan mit neuen Fragen ist mehr wert als eine Wiederholung der alten.
Shady Nathan Tawfik

Gründer & Cyber IT Security Engineer in Bielefeld. Offensive Security, Audits und Fullstack-Entwicklung. Mehr auf

Nur zu Bildungszwecken. Alle reproduzierbaren Befehle zielen auf meine eigene Lab-Umgebung (localhost), nie auf ein laufendes System. © 2026