~/blog/perfect-consent-one-patch-behindPOSTED
von Shady Nathan Tawfik · 8. Oktober 2026 · 8 min

Perfekter Consent, ein Patch zu spät: Die Kanzlei mit der saubersten Datenschutz-Schicht, die ich je gemessen habe

Die Website einer deutschen Kanzlei hatte die sauberste Consent-Architektur, die ich je gemessen habe — null Cookies und null Drittanbieter-Requests vor Opt-in. Gleichzeitig war sie einen Patch hinter einem öffentlichen Unauth-XSS-Fix, lieferte null Security-Header auf jeder Seite außer dem Login, gab anonym Tokens über ihre REST-API heraus und ließ die Vertrauenskette ihrer E-Mails halbfertig. Datenschutz-Reife und Sicherheits-Reife gehören unterschiedlichen Teams.

Interaktiv[blog-2.0]

TL;DR: Die Website einer deutschen Kanzlei machte Consent besser als alles, was ich je gemessen habe: Ein frisches Profil lud null Cookies, null Drittanbieter-Requests, null Iframes — nur der Consent-Manager selbst, Fonts lokal ausgeliefert. Sieben Tage nach Veröffentlichung des Fixes für eine unauthentifizierte Theme-XSS lief die Seite noch mit der verwundbaren Version, ohne CSP, die den Payload hätte eindämmen können. Dazu null von sechs Security-Headern auf der gesamten Oberfläche, ein anonymer CSRF-Token-Endpunkt auf der REST-API, öffentlich lesbare readme/license-Dateien und eine DMARC-Policy, die gefälschte Mandanten-Mails durchwinkt. Zwei Teams, zwei Reifegrade, eine Origin — und der schwächere bestimmt das Risiko.

Die Ausgangslage

Der Klient ist eine deutsche Kanzlei. Mandantengelder bewegen sich dort auf schriftliche Anweisung — E-Mail-Authentizität ist also kein Compliance-Thema, sondern eine operative Kontrolle. Meine Aufgabe war eine Prüfung der öffentlichen Web-Oberfläche: nicht-intrusiv, keine Payloads gegen den Live-Host, keine Anmeldeversuche. Header, DNS, TLS, REST-Proben und ein Headless-Browser mit frischem Profil.

Der erste Test ist immer Consent, weil er zeigt, wie eine Seite mit Besuchern umgeht, denen sie nichts schuldet. Er kam grün zurück, wie ich es noch nicht gesehen hatte: null Cookies, null Drittanbieter-Requests, null Iframes vor jeder Interaktion. Nur der Consent-Manager selbst lud. Google Fonts lokal. Das ist Lehrbuch — besser als Lehrbuch, weil die meisten Seiten mit Consent-Tool trotzdem irgendetwas feuern.

Dann lief dasselbe frische Profil gegen den Rest der Oberfläche — und das Bild teilte sich in zwei Hälften.

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

Das Muster

Reife in einer Dimension überträgt sich nicht

Wer den Consent-Stack konfiguriert hat, kümmerte sich, testete und verstand das Thema. Kein Drittanbieter-Request vor Einwilligung ist kein Standard — das ist eine Entscheidung, die jemand getroffen und überprüft hat. Dieselbe Seite lieferte null von sechs Basis-Security-Headern auf jeder Seite. Beide Fakten existierten aus demselben Grund nebeneinander, aus dem sie überall nebeneinander existieren: Datenschutz und Sicherheit haben verschiedene Verantwortliche, verschiedene Ticket-Warteschlangen, verschiedene Definitionen von „fertig". Eine Prüfung, die beim ersten grünen Bereich stehen bleibt, verpasst den Befund. Man muss jede Dimension einzeln messen, denn Reife sickert organisatorisch nicht seitwärts durch.

Ein Patch-Fenster ist ein öffentlicher Countdown, keine interne Notiz

Das Theme der Seite war einen Patch hinter einem unauthentifizierten reflected XSS, dessen Fix seit sieben Tagen öffentlich war. Die Startseite verrät die Version. Diese Version gegen aktuelle Advisories zu mappen dauert Minuten. Die Lücke zwischen „Fix veröffentlicht" und „installiert" ist von außen messbar, und jeder Scanner berechnet sie automatisch. Das Unangenehme ist nicht die Schwachstelle — es ist die Tatsache, dass ein Sieben-Tage-Fenster von außen nicht von einer nie gepatchten Seite zu unterscheiden ist. Die einzige Verteidigung ist, das Fenster zu schließen, bevor es zur Statistik wird.

„Der Login ist gehärtet" beweist Fähigkeit, nicht Abdeckung

Die Login-Seite hatte X-Frame-Options, eine frame-ancestors-Policy und ein sicheres Test-Cookie. Jede andere Seite hatte nichts. Diese Asymmetrie ist diagnostisch: Jemand in der Organisation kannte die Header-Basislinie und hat sie genau einmal angewandt — auf der Seite, die historisch angegriffen wird. Aber eine reflected XSS kümmert sich nicht um das Login-Formular — sie führt im Origin der Seite aus, auf der das Opfer gerade ist, und ein eingeloggtes Opfer ist genau das Ziel. Abdeckung ist die Metrik, nicht Fähigkeit.

Ein anonymer Nonce-Endpunkt ist ein vorgebautes Angriffswerkzeug

Der REST-Index umfasste 328 KB Routennamen — inklusive Security-Plugin- und Editor-Namespaces — und ein Endpunkt gab jedem anonymen Aufrufer einen CSRF-Nonce plus den Admin-Pfad zurück. Die Benutzer-Enumeration war an derselben API korrekt gesperrt, was zeigt: Die Sperre war bewusst, aber unvollständig. Token-Endpunkte sind das Schlimmste, was offen bleiben kann: Enumeration gibt dem Angreifer eine Karte, ein Nonce gibt ihm einen Schlüsselrohling, den er später zuschneiden kann.

In manchen Branchen ist E-Mail das Perimeter

SPF endete auf -all — den Teil bekommen alle hin. DMARC stand auf p=quarantine ohne gefundenen DKIM-Selector — fehlgeschlagene Alignment-Mails landen also in der Quarantäne statt im Ablehnungsordner, und die Spam-Entscheidung eines Mailbox-Providers wird zur letzten Verteidigungslinie. Für eine Kanzlei ist der realistische Betrug kein Spam: Es ist eine gefälschte Anweisung an einen Mandanten, mit neuer Bankverbindung. Diese Bedrohung berührt die Website nie. Sie entscheidet sich vollständig über DMARC und DKIM — was sie zu Mandantenschutz-Kontrollen macht, nicht zu Hygiene.

Die Kontrolle, die funktionierte — und den Auftrag prägte

Das Security-Plugin hat uns nach rund sechzig Requests von der Seite verbannt. Das ist eine funktionierende Kontrolle, und das gehört gesagt: Die meisten Seiten, die ich teste, reagieren überhaupt nicht. Sie hat auch den Audit diszipliniert — der Block wurde respektiert, betroffene Proben nach seiner Aufhebung nachgezogen, die Zeitleiste ist in den Belegen dokumentiert. Eine Verteidigung, die den Zeitplan eines Angreifers verändert, ist eine Verteidigung, die ihren Job macht.

TL;DR: The cleanest consent setup I have measured — zero cookies and zero third-party requests before opt-in — sat on a law firm site that was one patch behind a public unauth XSS fix, shipped zero of six security headers outside the login, handed out CSRF nonces to anonymous callers, and left DMARC at quarantine without DKIM.

Befunde

SchwereBefundBeleg
HOCHUnauthentifizierte reflected XSS im Theme, sieben Tage nach dem öffentlichen Fix — keine CSP, die sie eindämmtVersion auf der Leitung vs. Advisory-Zeitleiste; Lab-Spiegel gibt den Payload unescaped aus
HOCHNull von sechs Basis-Security-Headern auf jeder Seite außer dem LoginHeader-Capture von Startseite, Kontakt und Login im Direktvergleich
MITTELREST-Index (328 KB) anonym; ein Endpunkt liefert CSRF-Nonce und Admin-Pfad ohne LoginREST-Capture; Antwort des Token-Endpunkts
MITTELwp-cron.php öffentlich erreichbar — unauthentifizierter Cron-TriggerHTTP 200 auf der Live-Seite
MITTELDMARC nur p=quarantine, kein DKIM-Selector — gefälschte Mandanten-Mails werden quarantäniert, nicht abgelehntDNS-TXT-Records
MITTELKein SRI auf den externen Skripten des Consent-AnbietersStartseiten-HTML
NIEDRIGreadme.html und license.txt offen; Seiten zählbar (25 Seiten, 28 Beiträge, 181 Medien); ftp/dev-Alt-Hosts auf FremdservernPfad-Proben, REST-Zähler, DNS
NIEDRIGCMP-Storage-Eintrag vor Consent; 90-Tage-Zertifikatszyklus ohne HSTSHeadless-Capture, TLS-Datensatz
GUTConsent-Architektur: null Cookies, null Drittanbieter-Requests, null Iframes vor Opt-in; harte Pfade 403; Benutzer-Enumeration dreifach gesperrt; Rate-Limiting funktionierteFrisch-Profil-Capture; Pfad-Proben; der Block selbst

Der Angriffspfad

Versions-Fingerprint zeigt Theme einen Patch zurückAdvisory mappt Fix veröffentlicht vor sieben TagenKeine CSP, die das Skript eindämmtPräparierter Link erreicht einen eingeloggten RedakteurSkript läuft im Origin der KanzleiAnonymer Nonce-Endpunkt liefert TokensAdmin-Aktionen und Mandantendaten in Reichweite

Reproduktion im Labor

Jede Probe unten zielt auf einen Lab-Spiegel, den ich kontrolliere. Nichts davon richtet sich gegen ein Live-System.

~/code/bash bash
# 1. die Kontrolle: Consent in einem frischen Profil
TARGET_URL=http://lab.local/ node consent-audit.js
# <- Cookies: 0  Drittanbieter-Hosts: nur die CMP  Banner: vorhanden

# 2. dieselbe Origin, die sechs Header
curl -sI http://lab.local/ | grep -ciE \
  'strict-transport|content-security|x-frame|x-content-type|referrer-policy|permissions-policy'
# <- 0
curl -sI http://lab.local/wp-login.php | grep -iE 'x-frame|content-security'
# <- der Login ist gehärtet — Fähigkeit, nicht Abdeckung

# 3. Version vs. Advisory
curl -s http://lab.local/ | grep -oE 'ver=[0-9.]+' | sort -u
# <- Theme-Version ein Release hinter dem Fix

# 4. der Payload, nur im Labor
curl -s 'http://lab.local/?lang=%22%3E%3Cimg%20src%3Dx%20onerror%3Dalert(1)%3E' \
  | grep -o 'img src=x'
# <- verwundbarer Build gibt ihn roh aus; gehärteter Build liefert &lt;img

# 5. der Token-Endpunkt
curl -s http://lab.local/wp-json/security-plugin/v1/authenticate
# <- verwundbar: {success, nonce, adminUrl}; gehärtet: 401
~/code/text text
# Zusicherungen des Lab-Spiegels, verwundbar vs. gehärtet:
#   Security-Header-Anzahl      7 Checks: 0        -> 6
#   lang-Reflexion              roh                 -> escaped
#   readme.html / license.txt   200                 -> 404
#   REST-Nutzerliste            200 mit Klarnamen   -> 401
#   Token-Endpunkt              200 + Nonce         -> 401
#   wp-cron.php                 200                 -> 403

Erkennung im eigenen Bestand

  • Führe Consent-Test und Sicherheits-Test als getrennte Drills mit getrennten Verantwortlichen durch. Ein grünes Datenschutz-Ergebnis kann ein ungepatchtes Theme monatelang verstecken, weil niemand das Sicherheits-Backlog nach einem Compliance-Erfolg wieder aufmacht.
  • Verfolge Patch-Fenster als Zahl: pro Komponente die Tage zwischen Fix-Veröffentlichung und Deployment. Alarmiere oberhalb deiner Policy-Schwelle, statt auf den nächsten Release-Zug zu warten.
  • Prüfe die Header-Basislinie auf jedem Vhost und jeder Routenklasse, nicht nur am Login. Wenn der Login die einzige gehärtete Seite ist, wurde die Härtung per Hand gemacht — automatisier sie, oder sie wird sich nie ausbreiten.
  • Inventarisiere REST-Endpunkte danach, was sie anonymen Aufrufern zurückgeben. Jeder Endpunkt, der ein Nonce, Token oder URL liefert, ist ein Befund — auch wenn die Benutzer-Enumeration anderswo gesperrt ist.
  • Behandle DMARC und DKIM als Mandantenschutz-Kontrollen: erst DKIM, dann p=reject, sobald die Reports sauber bleiben. Quarantäne ist ein Vorschlag; Reject ist eine Entscheidung.
  • Messe die eigenen Verteidigungen von außen. Das Rate-Limit dieser Seite feuerte und veränderte den Auftrag — kenne die Schwelle und verifiziere, dass sie funktioniert, bevor ein Angreifer es tut.

Behebung

~/code/text text
# sofort
1. Theme auf den gefixten Release aktualisieren; neue Version auf der Leitung verifizieren
2. Header-Basislinie überall ausliefern (HSTS, CSP, X-Frame-Options, nosniff,
   Referrer-Policy, Permissions-Policy) — per .htaccess oder Vhost, nicht pro Seite

# innerhalb einer Woche
3. REST-API auf eingeloggte Nutzer beschränken; Vendor- und Token-Endpunkte
   für anonyme Aufrufer deaktivieren
4. readme.html, license.txt und wp-cron.php sperren; auf DISABLE_WP_CRON
   mit System-Cron umstellen
5. DKIM am Mail-Gateway aktivieren und Selector publizieren; Umstieg auf
   DMARC p=reject nach 30 sauberen Report-Tagen planen

# innerhalb eines Monats
6. SRI oder CSP-Hashes für den Consent-Anbieter; security.txt (200);
   CAA ergänzen, Alt-Hosts inventarisieren, Zertifikats-Renewal-Alerting

Once an attacker gains access, they can perform the following actions:

Unauthenticated reflected XSS in the theme with no CSP: crafted link to a logged-in editor, script runs in the firm origin
Zero security headers outside the login: no HSTS, no CSP, no frame protection — every browser-side mitigation absent
DMARC quarantine without DKIM: forged client instructions are evaluated, not rejected — money-transfer fraud risk
Anonymous REST endpoint returns CSRF nonce and admin path; 328 KB index and media counts publicly enumerable
Public wp-cron trigger, open readme/license, legacy ftp/dev hosts — version and config intelligence for free

Erkenntnisse

  • Datenschutz-Reife überträgt sich nicht auf Sicherheits-Reife. Sie haben verschiedene Verantwortliche, verschiedene Warteschlangen — und die schwächere bestimmt das Risiko.
  • Ein Patch-Fenster ist extern, öffentlich und zählbar: Version auf der Leitung plus Fix-Veröffentlichungsdatum. Sieben Tage ungepatcht und nie gepatcht sehen von außen identisch aus.
  • Eine gehärtete Seite beweist, dass jemand sich gekümmert hat. Jede Route gehärtet beweist, dass die Kontrolle existiert. Reflected XSS zielt auf die Seiten, die du nicht gehärtet hast.
  • Token-Endpunkte sind schlimmer als Enumeration. Eine Karte ist Aufklärung; ein Nonce ist ein Angriffswerkzeug.
  • In professionellen Dienstleistungen ist E-Mail-Authentizität Mandantenschutz. SPF mit -all ist der Anfang; DKIM und p=reject sind das Ende.
  • Lob, was funktioniert. Die Consent-Schicht und der Rate-Limiter funktionierten wirklich — der Bericht sagt es, weil Sicherheitsberatung, die nur Fehler zählt, keine Beratung ist, sondern eine Anzeigetafel.
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