CSP Best Practices: Leitfaden zur Einführung einer sicheren CSP
Die Einführung einer Content Security Policy (CSP) gehört zu den effektivsten Massnahmen, um eine Webanwendung gegen Cross-Site Scripting (XSS) zu härten. Allerdings ist die Konfiguration fehleranfällig: Ist die Policy zu locker, bietet sie keinen Schutz; ist sie zu streng, werden legitime JavaScript-Funktionen blockiert und die Website funktioniert nicht mehr. Die folgenden Best Practices zeigen den Pfad zu einer sicheren, praxistauglichen CSP.
Die CSP ist nur ein – wenn auch der mächtigste – Baustein einer umfassenden Absicherung. Sie gehört in jede Security-Header-Checkliste und wirkt am besten im Verbund mit weiteren Headern wie HSTS und X-Frame-Options.
Der strukturierte 3-Schritt-Rollout
Führen Sie eine CSP niemals direkt im Blockade-Modus ein. Nutzen Sie stattdessen dieses bewährte Vorgehen:
1. Schritt: Die Bestandsaufnahme (Report-Only)
Hinterlegen Sie eine vorläufige Policy über den HTTP-Header Content-Security-Policy-Report-Only.
- Funktionsweise: Der Browser blockiert keine Skripte, meldet aber jeden Verstoss gegen die Richtlinie als JSON-Paket an eine von Ihnen definierte Reporting-URL (z. B. über ein Tool oder ein internes Logging).
- Dauer: Lassen Sie diesen Modus für mindestens 7 bis 14 Tage laufen, um alle regulären Nutzungsszenarien der Website abzubilden.
2. Schritt: Auswertung und Anpassung
Analysieren Sie die Fehlerberichte:
- Welche Skripte, Styles oder Bilder wurden gemeldet?
- Fügen Sie legitimen Inline-Skripten dynamische Nonces (kryptografische Einmalschlüssel) hinzu oder hinterlegen Sie deren SHA-Hashes in der CSP-Konfiguration.
- Entfernen Sie nicht genutzte Drittanbieter-Dienste.
3. Schritt: Die Scharfschaltung
Haben Sie alle legitimen Quellen erfasst und treten in den Reports keine Fehlmeldungen mehr auf, benennen Sie den Header in Content-Security-Policy um. Der Browser blockiert nun aktiv jeden Verstoss.
Die 5 goldenen CSP-Regeln
Um eine hohe Schutzwirkung zu erzielen, sollten Sie diese Richtlinien befolgen:
1. Verzicht auf unsafe-inline
Das Erlauben von unsafe-inline in der script-src-Direktive hebelt den XSS-Schutz fast vollständig aus, da Angreifer Schadcode wieder direkt im HTML ausführen können. Nutzen Sie stattdessen Nonces oder Hashes für Inline-Skripte.
2. Verzicht auf unsafe-eval
Vermeiden Sie die Ausführung von Text als Code (z. B. über eval(), new Function() oder setTimeout("string")). Diese Funktionen öffnen Angreifern Hintertüren für die Ausführung eingeschleuster Befehle. Modifizieren Sie Ihr JavaScript so, dass es ohne eval auskommt.
3. Plugins blockieren (object-src 'none')
Veraltete Browser-Plugins wie Flash, Silverlight oder Java-Applets sind berüchtigte Sicherheitslücken. Setzen Sie object-src daher standardmässig immer auf 'none'.
4. Base-URL sperren (base-uri 'self')
Das <base>-HTML-Tag definiert die Basis-URL für alle relativen Links auf der Seite. Angreifer können dieses Tag manipulieren (Base Jacking), um relative Skriptaufrufe auf ihre eigenen Server umzulenken. Sperren Sie dies mit base-uri 'self' oder base-uri 'none'.
5. Fallback einschränken (default-src 'self')
Beginnen Sie Ihre Policy immer mit einem restriktiven Fallback: default-src 'self'. Dies stellt sicher, dass für alle nicht explizit definierten Direktiven (wie media-src oder font-src) die sicherste Standardeinstellung gilt.
Schwache vs. starke CSP im direkten Vergleich
Der Unterschied zwischen einer wirkungslosen und einer schützenden Policy liegt oft in wenigen Schlüsselwörtern:
| Direktive | Schwach (vermeiden) | Stark (empfohlen) |
|---|---|---|
| script-src | 'self' 'unsafe-inline' | 'self' 'nonce-rAnd0m' |
| object-src | nicht gesetzt | 'none' |
| base-uri | nicht gesetzt | 'self' |
| default-src | * | 'self' |
Schwach (bietet kaum XSS-Schutz):
Content-Security-Policy: default-src *; script-src 'self' 'unsafe-inline'
Stark (Nonce-basiert):
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-rAnd0m'; object-src 'none'; base-uri 'self'
Jedes legitime Inline-Skript erhält dann das passende Nonce-Attribut (<script nonce="rAnd0m">), während eingeschleuste Skripte ohne gültige Nonce blockiert werden.
Typische Fehlkonfigurationen und ihre Folgen
In der Praxis scheitern CSPs immer wieder an denselben Mustern:
| Fehlkonfiguration | Folge | Korrektur |
|---|---|---|
unsafe-inline in script-src | XSS-Schutz praktisch ausgehebelt | Nonces oder Hashes verwenden |
| Ganze CDN-Domain freigegeben | Bypass über alte Bibliotheken | Nur konkrete Dateien/Hashes erlauben |
Kein object-src | Plugin-basierte Angriffe möglich | object-src 'none' setzen |
| CSP nur im Report-Only-Modus belassen | Kein realer Schutz aktiv | Nach Testphase scharf schalten |
Wer diese Punkte vermeidet, kommt einer Bewertung im grünen Bereich beim CSP Evaluator sehr nahe.
[!TIP] Eine starke CSP schützt Ihre Kunden zuverlässig vor Schadcode-Ausführungen. Validieren Sie die Stärke und Kompatibilität Ihrer CSP-Direktiven mit dem kostenlosen CSP Evaluator auf balou.tools.
Häufig gestellte Fragen (FAQ)
Wie führe ich eine CSP ohne Ausfallzeiten ein?
Nutzen Sie die Zwei-Schritt-Methode. Starten Sie mit dem Header `Content-Security-Policy-Report-Only` und werten Sie die eingehenden Fehlerberichte aus. Erst wenn keine legitimen Skripte mehr blockiert werden, schalten Sie auf den scharfen `Content-Security-Policy` Header um.
Was ist das Problem mit Domain-Whitelists bei script-src?
Wenn Sie eine ganze CDN-Domain (z. B. `https://cdnjs.cloudflare.com`) freigeben, können Angreifer dort gelistete, veraltete oder anfällige Bibliotheken (z. B. alte Angular-Versionen) nutzen, um Ihre CSP zu umgehen (Bypassing).
Was ist der Unterschied zwischen einer Nonce und einem Hash?
Eine Nonce ist ein zufälliger Einmalwert, der bei jedem Seitenaufruf neu erzeugt und sowohl im Header als auch im script-Tag gesetzt wird – ideal für serverseitig gerenderte Seiten. Ein Hash ist die Prüfsumme eines konkreten Inline-Skripts und eignet sich für statische, unveränderliche Skripte.
Brauche ich eine CSP, wenn ich bereits andere Security Header setze?
Ja. Header wie X-Frame-Options oder HSTS schützen vor anderen Angriffsarten (Clickjacking bzw. Downgrade). Gegen Cross-Site-Scripting ist die CSP der zentrale Schutz und lässt sich durch keinen anderen Header ersetzen.