~/blog/twenty-findings-one-wordpress-sitePOSTED
von Shady Nathan Tawfik · 30. Mai 2026 · 3 min

Zwanzig Befunde, eine Plattform: Wie Volumen die Behebungsreihenfolge verändert

Ein Industrielieferant mit grosser Content-Oberfläche ergab zwanzig Befunde in sieben Kategorien. Der Wert lag in der Reihenfolge, nicht in der Anzahl.

Interaktiv[blog-2.0]

TL;DR: Zwanzig Befunde sind meist vier Ursachen, die sich über zwanzig Seiten ausdrücken. Ich habe sie gruppiert, die Fixes nach Abhängigkeiten statt nach Schwere geordnet und erkläre, warum die Mail-Authentifizierung zuerst kam.

Ausgangslage

Ich habe das Ziel als Black-Box geprüft: keine Zugangsdaten, nur die öffentlich sichtbare Fläche. Das ist, was ich sah, bevor ich etwas angefasst habe.

Ein globaler Industrielieferant mit mehrsprachiger Content-Plattform, grosser Mediathek, Online-Katalog und Kundenservice-Integration. Geprüft wurden die Content-Oberfläche, die Mediathek, E-Mail-Authentifizierung, Header-Policy und der Plugin-Bestand.

Ich habe alle identifizierenden Informationen entfernt. Das Ziel wird ausschließlich nach Branche und Technologieklasse beschrieben, damit das Muster übertragbar bleibt.

Das Muster

Das Muster, das ich erkannt habe — und das ich in ähnlichen Landschaften immer wieder finde:

Zwanzig Befunde sind nicht zwanzig Probleme. Es sind meist drei oder vier Probleme, die sich über zwanzig Seiten ausdrücken. Derselbe fehlende Header erscheint in jedem Template, dieselbe User-Enumeration liefert dieselben acht Konten in jeder Sprachvariante.

Nach Gruppierung ergibt sich die Reihenfolge aus Abhängigkeiten statt aus Schwere. E-Mail-Authentifizierung zuerst, weil Phishing gegen einen Lieferanten das plausibelste Szenario ist. Header-Policy zweitens, weil eine Zeile pro Stufe eine Angriffsklasse dauerhaft stoppt. User-Enumeration drittens, weil sie kein direktes Exploit ist, aber die Eintrittsbedingung für Credential-Angriffe.

Die Kategorie, die meist zuletzt kommt und nicht sollte, ist Versionshygiene. Veraltete Plugins erzeugen permanente Arbeit und gehören meist einer Agentur, was sie zum Gespräch statt zur Aufgabe macht.

TL;DR: Ein Industrielieferant mit grosser Content-Oberfläche ergab zwanzig Befunde in sieben Kategorien. Der Wert lag in der Reihenfolge, nicht in der Anzahl.

Befunde

SchweregradBefundNachweis
HOCHBenutzer-Enumeration über alle SprachvariantenDieselben Konten in jedem Locale exponiert
HOCHKeine Sicherheits-Header in irgendeinem TemplateLücke auf Template-Ebene, nicht auf Seitenebene
MITTELE-Mail-Authentifizierung für die Absenderdomain nicht erzwungenNewsletter- und Bestellmail fälschbar
MITTELMediathek ohne Authentifizierung enumerierbarVollständiges Asset-Inventar lesbar
MITTELAdministrative Pfade unter vorhersagbarem Präfix erreichbarKonsistenter Entdeckungspfad
NIEDRIGPlugin- und Core-Versionen preisgegebenGenauer Build über alle Locales identifizierbar

Der Angriffspfad

Twenty findingsGroup by causeMail policyTemplate headersUser enumerationMedia accessFix firstFix secondFix third and monitorFix with ownership decision

Reproduktion im Labor

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

Eigene Befunde nach Ursache statt nach Seite gruppieren

~/code/bash bash
# derselbe Befund in jedem Locale der eigenen Seite
$ for loc in en de fr it; do
    printf '%-4s users=%s headers=%s\n' "$loc" \
      "$(curl -s "https://example.org/$loc/wp-json/wp/v2/users" | grep -c '"slug"')" \
      "$(curl -sI "https://example.org/$loc/" | grep -ciE 'content-security-policy|x-frame-options')"
done

Erkennung in eigener Infrastruktur

Die Template-Lücke über jedes Ihrer Locales messen

~/code/bash bash
$ for loc in en de fr it es; do
    n=$(curl -sI "https://example.org/$loc/" | grep -ciE 'content-security-policy|x-frame-options|x-content-type-options|referrer-policy')
    printf '%-4s security-headers=%s/4\n' "$loc" "$n"
done

# und das Medieninventar
$ curl -s 'https://example.org/wp-json/wp/v2/media?per_page=100' \
  | python3 -c 'import json,sys; d=json.load(sys.stdin); print("Medienobjekte:", len(d))'

Behebung

Das Template einmal fixen, nicht zwanzig Seiten

~/code/apache apache
# die Basislinie in den Virtual Host, nicht in jedes Template
<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Content-Security-Policy "default-src 'self'; frame-ancestors 'self'"
</IfModule>

ServerTokens Prod
ServerSignature Off

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

Benutzer-Enumeration über alle Sprachvarianten
Keine Sicherheits-Header in irgendeinem Template
E-Mail-Authentifizierung für die Absenderdomain nicht erzwungen
Mediathek ohne Authentifizierung enumerierbar
Administrative Pfade unter vorhersagbarem Präfix erreichbar

Fazit — was ich daraus mitnehme

  • Zwanzig Befunde sind meist vier Ursachen. Gruppieren Sie vor dem Priorisieren.
  • Fixen Sie das Template, nicht die Seiten; Seiten-Fixes überleben kein Redesign.
  • E-Mail-Authentifizierung ist DNS, schwer versehentlich zurückzunehmen, und Phishing ist die plausible Bedrohung.
  • Templates werden aus einer sauberen Kopie neu deployed. Legen Sie die Header-Baseline ins Repository, nicht auf den Server.

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