Sicherheits-Ratgeber
Security-Header zu setzen ist eine einmalige Aufgabe. Sie zu behalten nicht: der nächste Deploy, eine CDN-Regel oder ein Plugin-Update kann sie entfernen oder aufweichen, und auf der Seite sieht dabei nichts anders aus. Dieser Ratgeber zeigt drei Wege, das zu bemerken, mit Skripten, die Sie so übernehmen können, und einem ehrlichen Hinweis darauf, was jeder davon übersieht.
01 Warum es wichtig ist
Security-Header stehen in Konfiguration, die viele Hände anfassen: der Webserver, die Anwendung, ein CDN oder Reverse Proxy davor und die Plugins eines CMS. Eine Server-Migration, die ein Include vergisst, ein nginx-location-Block mit eigener add_header-Zeile, der still jeden vom server-Block geerbten Header verwirft, oder eine CDN-Regel, die Antworten umschreibt, genügen. Die Website funktioniert weiter, und genau deshalb bemerkt es niemand.
Eine einmalige Prüfung sagt Ihnen nur, wie es an dem Tag aussah, an dem Sie sie gemacht haben. Überwachen heißt, die ausgelieferten Header immer wieder mit einem bekannten guten Stand zu vergleichen und benachrichtigt zu werden, wenn sie abweichen.
02 Was Sie beobachten
Jeder Weg unten vergleicht gegen einen Soll-Stand: die Header und Werte, die Ihre Website senden soll. Führen Sie ihn als einfache Textdatei mit einem Header pro Zeile, Namen kleingeschrieben, sortiert. So erscheint eine Änderung als lesbarer Diff statt als Textwand.
content-security-policy: default-src 'self'; script-src 'self' 'nonce-X'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none' permissions-policy: camera=(), microphone=(), geolocation=(), payment=() referrer-policy: strict-origin-when-cross-origin strict-transport-security: max-age=31536000; includeSubDomains x-content-type-options: nosniff x-frame-options: DENY Zwei Dinge ändern sich bei jeder Anfrage und müssen vor dem Vergleich neutralisiert werden: eine CSP-Nonce, die je Antwort neu ist, und Header wie date oder set-cookie, die nichts über Ihre Sicherheit aussagen. Die Skripte unten behalten nur die Security-Header und ersetzen jede Nonce durch einen festen Platzhalter.
03 Weg 1
Die einfachste Überwachung ist ein Shell-Skript auf einem Server, den Sie ohnehin betreiben. Es holt die Header, reduziert sie auf die Security-Header, vergleicht sie mit dem Ergebnis des vorigen Laufs und schickt eine Mail, wenn sie abweichen. Der erste Lauf legt nur den Soll-Stand an.
#!/bin/sh set -eu url="https://www.example.com/" dir="/var/lib/header-watch" mkdir -p "$dir" curl -fsS -o /dev/null -D "$dir/raw.txt" "$url" tr -d '\r' < "$dir/raw.txt" \ | sed -E "s/'nonce-[^']+'/'nonce-X'/g" \ | awk -F': ' 'tolower($1) ~ /^(content-security-policy(-report-only)?|permissions-policy|referrer-policy|strict-transport-security|x-content-type-options|x-frame-options)$/ { print tolower($1) ": " substr($0, length($1) + 3) }' \ | sort > "$dir/current.txt" if [ -f "$dir/baseline.txt" ] && ! diff -u "$dir/baseline.txt" "$dir/current.txt" > "$dir/diff.txt"; then mail -s "Security headers changed: $url" ops@example.com < "$dir/diff.txt" fi mv "$dir/current.txt" "$dir/baseline.txt" MAILTO=ops@example.com */30 * * * * /usr/local/bin/header-watch.sh curl -f lässt das Skript bei einem Fehlerstatus scheitern, und set -e bricht genau dort ab. Cron schickt dann den curl-Fehler an MAILTO, statt dass das Skript meldet, alle Header seien verschwunden. Jede Änderung wird einmal gemeldet, weil der aktuelle Stand danach der neue Soll-Stand ist. Alle 30 Minuten oder stündlich genügt; Header ändern sich mit Deploys, nicht im Sekundentakt.
04 Weg 2
Ein Cronjob bemerkt eine Änderung innerhalb der Stunde. Eine Prüfung in Ihrer Deploy-Pipeline bemerkt sie in derselben Minute und kann den Deploy benennen, der sie verursacht hat. Das Skript unten schlägt fehl, wenn ein Pflicht-Header fehlt oder die Richtlinie unsafe-inline oder unsafe-eval erlaubt oder kein form-action hat.
#!/bin/sh set -eu curl -fsS -o /dev/null -D headers.txt "$1" tr -d '\r' < headers.txt > headers.clean fail=0 for header in strict-transport-security content-security-policy x-content-type-options referrer-policy; do if ! grep -qi "^$header:" headers.clean; then echo "missing header: $header" fail=1 fi done csp=$(awk 'tolower($0) ~ /^content-security-policy:/' headers.clean) case "$csp" in *"'unsafe-inline'"*) echo "policy allows 'unsafe-inline'"; fail=1 ;; esac case "$csp" in *"'unsafe-eval'"*) echo "policy allows 'unsafe-eval'"; fail=1 ;; esac case "$csp" in *form-action*) ;; *) echo "policy has no form-action"; fail=1 ;; esac exit "$fail" security-headers: stage: .post image: alpine:3.20 before_script: - apk add --no-cache curl script: - sh ci/check-headers.sh "$PRODUCTION_URL" Die Stage .post läuft in GitLab CI immer zuletzt, nach dem Deploy-Job. In GitHub Actions läuft dasselbe Skript als Schritt nach dem Deploy-Schritt. Die Prüfung ist absichtlich streng: sie lehnt unsafe-inline auch neben einer Nonce ab, wo Browser es ignorieren. Lockern Sie diese Zeile, wenn Ihre Richtlinie auf den Rückfall für alte Browser setzt.
05 Weg 3
Wenn Sie keine Skripte selbst betreiben wollen, scannt das Monitoring Ihre Website in einem festen Abstand neu, alle 1, 3, 7, 14 oder 30 Tage, standardmäßig alle 7. Jeder Lauf ist ein vollständiger Scan und deckt damit nicht nur die Header ab, sondern auch TLS, Cookies, DNS- und Mail-Einträge und die übrigen Dimensionen des Berichts.
Nach jedem Lauf vergleicht es den neuen Scan mit dem vorigen und schickt eine Mail, wenn die Gesamtbewertung sinkt oder ein Befund auftaucht, den es vorher nicht gab, mit den Titeln der neuen Befunde. Es meldet nicht jeden geänderten Header-Wert: ein neuer Host in einer bereits starken Richtlinie oder eine weitere Schwäche in einer Richtlinie, die schon als schwach gemeldet ist, ändert weder Bewertung noch Befunde und löst deshalb keine Mail aus. Dafür ist der Diff aus Weg 1 oder 2 das richtige Werkzeug.
Das Monitoring ist Teil des Agency-Tarifs und umfasst bis zu 25 Websites. Ohne es können Sie jetzt einen kostenlosen Scan starten, nach Ihrem nächsten Deploy erneut scannen und aus dem Bericht den Vergleich öffnen. Er zeigt, welche Befunde behoben sind, welche neu dazugekommen sind und wie sich die Bewertungen bewegt haben.
06 Welcher Weg
Findet. Jede Änderung an einem beobachteten Header-Wert, auch einen zusätzlichen Host in der Richtlinie, innerhalb eines Intervalls.
Übersieht. Alles außerhalb der aufgeführten Header und andere Seiten als die eine URL. Es läuft auf Ihrem Server und steht still, wenn der steht.
Findet. Fehlende Header und die geprüften Schwächen der Richtlinie, sofort und dem Deploy zugeordnet, der sie verursacht hat.
Übersieht. Änderungen, die nicht durch Ihre Pipeline laufen: CDN-Regeln, Hosting-Oberflächen, im Adminbereich aktualisierte CMS-Plugins.
Findet. Jeden neuen Befund und jede sinkende Bewertung, über Header, TLS, Cookies, DNS und den Rest des Berichts, egal woher die Änderung kommt.
Übersieht. Wertänderungen, die keinen neuen Befund erzeugen und die Bewertung nicht senken, und alles zwischen zwei geplanten Läufen.
Die Wege ergänzen sich: die CI-Prüfung stoppt Ihre eigenen Fehler, der Diff fängt jede Wertänderung, und der Scan bemerkt, was aus Quellen schlechter wird, die Sie nicht kontrollieren. Speziell für die Content Security Policy gibt es einen eigenen Ratgeber zum Erkennen von Änderungen.
07 Fragen
Nach jedem Deploy und zusätzlich regelmäßig für Änderungen, die nicht durch Ihre Pipeline laufen. Stündlich reicht für eine curl-Prüfung völlig, wöchentlich ist ein vernünftiger Standard für einen vollständigen Scan, denn Header ändern sich mit der Konfiguration, nicht mit dem Verkehr.
Fast immer wegen einer CSP-Nonce, die in jeder Antwort neu ist, oder weil date, set-cookie oder eine Request-ID in den Vergleich geraten sind. Vergleichen Sie nur die Security-Header und ersetzen Sie die Nonce vor dem Diff durch einen festen Platzhalter, wie es die Skripte oben tun.
Nein. Es meldet, wenn die Gesamtbewertung sinkt oder ein neuer Befund auftaucht. Ein verschwundener Header, eine Richtlinie, die auf Report-Only umgestellt wird, oder eine bisher saubere Richtlinie, die unsafe-inline dazubekommt, fällt so auf. Ein geänderter Wert ohne neuen Befund, etwa ein zusätzlicher Skript-Host in einer starken Richtlinie, nicht. Dafür vergleichen Sie die Header-Werte direkt.
Beginnen Sie mit ihr und nehmen Sie dann die Seiten dazu, die anders ausgeliefert werden: Login, Kasse, die API und alles hinter einem eigenen location-Block oder einer eigenen Anwendung. Header werden oft je Pfad gesetzt, und ein fehlender Header auf der Login-Seite wiegt schwerer als einer auf der Startseite.
08 Im Detail
Die Überwachung sagt Ihnen, wann sich etwas geändert hat. Diese Ratgeber erklären, wie jeder Header überhaupt aussehen sollte.
Was jeder Response-Header bewirkt, welche Ihre Website senden sollte und wie Sie sie richtig konfigurieren.
Der stärkste Schutz gegen Cross-Site-Scripting: welche Direktiven Sie setzen, wie Sie eine Richtlinie im Report-Only-Modus einführen und wie Sie erzwingend werden, ohne Ihre Website zu zerlegen.
Strict-Transport-Security erklärt: was max-age, includeSubDomains und preload wirklich bewirken und warum die Preload-Liste eine Entscheidung ist, die Sie nicht schnell zurücknehmen können.
Secure, HttpOnly und SameSite: die Cookie-Attribute, die eine Sitzung vor Skripten und fremden Seiten schützen, samt Einstellungen für einen typischen Stack.
Wie eine unsichtbare Überlagerung aus einem Besucherklick eine Aktion auf Ihrer Website macht, und die zwei Header, die das verhindern: X-Frame-Options für ältere Clients, frame-ancestors für alles andere.
Welcher Teil Ihrer URLs an fremde Seiten geht, wenn ein Besucher weiterklickt: die fünf Werte, die zählen, was jeder davon preisgibt und welcher der sinnvolle Standard ist.
Kamera, Mikrofon, Standort und Bezahlfunktion für Ihre Website und alle eingebetteten Inhalte abschalten: die Syntax der Positivliste und warum eine nicht genannte Funktion keine abgeschaltete Funktion ist.
Die Einträge, die verhindern, dass jemand in Ihrem Namen Mails verschickt, und der, der Ihre DNS-Antworten ehrlich hält: was jeder leistet und in welcher Reihenfolge Sie sie einführen.
Die Datei, die Sicherheitsforschern sagt, wohin eine Schwachstelle gemeldet wird. Zwei Pflichtfelder, zehn Minuten Arbeit, und der Unterschied zwischen einer privaten und einer öffentlichen Meldung.
Wie sich eine Richtlinie durch Deploys, Plugins und CDN-Regeln unbemerkt ändert und wie Sie es merken: ein Header-Diff, Verstoßmeldungen über report-to und was ein Scan-Vergleich zeigen kann und was nicht.
Weiterlesen
Jeder Ratgeber steht für sich, zusammen decken sie ab, worauf unser Scanner schaut. Wählen Sie den, der Ihrer nächsten Frage am nächsten kommt.
Starten Sie einen kostenlosen Scan für Ihren Soll-Stand: jeder Security-Header bewertet und verständlich erklärt. Scannen Sie nach Ihrem nächsten Deploy erneut und vergleichen Sie, oder lassen Sie das Agency-Monitoring das regelmäßig erledigen.