Content Security Policy (CSP) im Detail: Schutz vor XSS
Die Content Security Policy (CSP) ist einer der mächtigsten und zugleich komplexesten Security Header zur Absicherung von Webanwendungen. Sie dient als effektive Schutzmauer gegen Cross-Site Scripting (XSS) und Data-Injection-Angriffe. Über die CSP teilt der Server dem Browser – als HTTP-Response-Header – eine Whitelist von vertrauenswürdigen Quellen mit, von denen Skripte, Styles, Bilder oder Verbindungen geladen und ausgeführt werden dürfen. Alles, was nicht auf dieser Liste steht, blockiert der Browser rigoros. Konkrete Vorlagen finden Sie in den CSP Best Practices.
Das Kernproblem: Unkontrollierte Skript-Ausführung
Ohne CSP vertraut ein Browser jedem JavaScript-Code, der im HTML-Dokument steht. Gelingt es einem Angreifer, eigenen Code (z. B. über manipulierte Benutzereingaben oder gehackte Drittanbieter-Skripte) in die Seite einzuschleusen, führt der Browser diesen aus. Der Angreifer kann dann Cookies stehlen, Logins fälschen oder Kundendaten abfangen.
Die CSP löst dieses Problem, indem sie dem Browser die Ausführung unautorisierter Skripte verbietet.
Die wichtigsten CSP-Direktiven (Directives)
Eine Content Security Policy wird als Response-Header mit einer Reihe von Direktiven deklariert:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trustedscripts.com; img-src 'self' data:;
default-src: Der Fallback für fast alle anderen Direktiven. Steht hier'self', dürfen Ressourcen standardmässig nur von der eigenen Domain geladen werden.script-src: Definiert die erlaubten Quellen für JavaScript.style-src: Regelt, von welchen Domains CSS-Dateien geladen werden dürfen.img-src: Bestimmt die erlaubten Quellen für Bilder (z. B.'self'oderdata:für Inline-Base64-Grafiken).frame-ancestors: Legt fest, welche Domains diese Website in einem iframe einbetten dürfen. Dies ist der moderne, standardisierte Nachfolger des älterenX-Frame-Options-Headers.
Das Verbot von Inline-Skripten und die Lösung
Eine sichere CSP verbietet standardmässig die Ausführung von direkt im HTML eingebetteten Skripten (z. B. <script>alert('XSS')</script> oder Inline-Event-Handlern wie onclick="..."). Das Schlüsselwort 'unsafe-inline' hebt dieses Verbot auf, schwächt die CSP jedoch dramatisch ab und sollte im produktiven Einsatz vermieden werden.
Um legitime Inline-Skripte dennoch sicher auszuführen, bietet die CSP zwei Verfahren:
A. Nonces (Kryptografische Einmal-Schlüssel)
Der Server generiert bei jedem Seitenaufruf einen zufälligen, kryptografischen Wert (Nonce) und fügt ihn sowohl im CSP-Header als auch im HTML-Tag hinzu:
- Header:
script-src 'nonce-d3g8a2k9' - HTML:
<script nonce="d3g8a2k9">console.log('Sicher')</script>Da ein Angreifer den dynamischen Nonce-Wert nicht erraten kann, blockiert der Browser nicht-autorisierte Skripte ohne passenden Nonce.
B. Hashes (Kryptografische Prüfsummen)
Der Server berechnet vorab den SHA-256-Hash des Inline-Skripts und hinterlegt diesen im CSP-Header.
- Header:
script-src 'sha256-R3x5v...'Der Browser vergleicht vor der Ausführung den Hashwert des Skripts im HTML mit dem Wert im Header. Stimmen sie überein, wird das Skript ausgeführt.
Überwachung durch Reporting
Mit den Tags report-uri oder report-to können Sie den Browser anweisen, jeden Verstoss gegen die CSP automatisch als JSON-Bericht an einen Server zu senden. Dies ist äusserst wertvoll, um unbemerkte XSS-Angriffe im Live-Betrieb aufzudecken oder Fehler bei der eigenen CSP-Konfiguration schnell zu beheben.
Schwache vs. starke CSP im direkten Vergleich
Eine CSP mit unsafe-inline bietet kaum Schutz vor XSS, weil eingeschleuste Inline-Skripte weiterhin ausgeführt werden. Die folgende Gegenüberstellung zeigt den Unterschied:
| Aspekt | Schwach (vermeiden) | Stark (empfohlen) |
|---|---|---|
script-src | 'self' 'unsafe-inline' | 'self' 'nonce-rAnd0m' |
| Inline-Skripte | uneingeschränkt erlaubt | nur mit gültigem Nonce |
object-src | nicht gesetzt | 'none' |
base-uri | nicht gesetzt | 'self' |
| XSS-Schutz | praktisch keiner | hoch |
Schwach (vermeiden):
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
Stark (empfohlen, Nonce-basiert):
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-rAnd0m'; object-src 'none'; base-uri 'self'
Jedes erlaubte Skript erhält dann ein passendes Nonce-Attribut (<script nonce="rAnd0m">). Ergänzend sollten Sie verwandte Header wie X-Frame-Options bzw. frame-ancestors setzen und Ihre gesamte Konfiguration mit der Security-Header-Checkliste abgleichen.
Typische Fehlkonfigurationen
| Fehler | Risiko | Besser |
|---|---|---|
'unsafe-inline' im script-src | XSS bleibt möglich | Nonces oder Hashes nutzen |
default-src * | Alles erlaubt, kein Schutz | restriktiv mit 'self' starten |
object-src vergessen | Flash/Plugin-Injection | object-src 'none' |
| Direkt scharf statt Report-Only | Funktionsausfälle | erst Report-Only testen |
[!TIP] Das Erstellen einer fehlerfreien, restriktiven Content Security Policy ist eine anspruchsvolle Aufgabe, die durch das Hinzufügen neuer Funktionen auf der Website stetig angepasst werden muss. Analysieren Sie Ihre CSP und decken Sie Schwachstellen auf mit dem kostenlosen CSP Evaluator auf balou.tools.
Häufig gestellte Fragen (FAQ)
Wie schützt eine CSP vor Cross-Site Scripting (XSS)?
Selbst wenn ein Angreifer erfolgreich Schadcode in Ihre Website einschleust (z. B. durch ein unsicheres Gästebuch), blockiert der Browser die Ausführung dieses Skripts, sofern die Domain des Angreifers nicht explizit in der CSP-Whitelist freigegeben ist.
Was bewirkt der Status „Report-Only“?
Mit dem Header `Content-Security-Policy-Report-Only` können Sie eine CSP testen. Verstösse werden an eine definierte URL gemeldet (Report-To), aber der Browser blockiert die Skripte noch nicht. Dies verhindert Ausfälle beim Testen neuer Regeln.