Implementierung der Content Security Policy (CSP)
Der HTTP-Header Content-Security-Policy
bietet eine feingesteuerte Kontrolle über den Code, der auf einer Website geladen werden kann, und was ihm erlaubt ist zu tun.
Problem
Das Hauptproblem, auf das sich dieser Artikel konzentriert, sind Cross-Site-Scripting (XSS) Angriffe. Diese entstehen in der Regel durch mangelnde Kontrolle und Bewusstsein über die Quellen, aus denen Website-Ressourcen geladen werden. Dieses Problem wird schwieriger zu handhaben, je größer und komplexer Websites werden und je mehr sie auf Drittanbieterressourcen wie JavaScript-Bibliotheken angewiesen sind.
Hinweis: CSP ist ein Teil einer umfassenden Strategie zum Schutz vor XSS-Angriffen. Es gibt auch andere wichtige Faktoren, wie z. B. Ausgabe-Kodierung und Bereinigung.
CSP kann auch helfen, andere Probleme zu lösen, die in anderen Artikeln behandelt werden:
- Verhinderung von Clickjacking durch Verhinderung, dass Ihre Seite in
<iframe>
-Elemente eingebettet wird. Dies erfolgt durch die CSP-Direktiveframe-ancestors
. - Verhinderung von Manipulator-in-the-Middle (MiTM) Angriffen durch Hochstufung aller HTTP-Verbindungen zu HTTPS. Dies wird unterstützt durch die CSP-Direktive
upgrade-insecure-requests
. Siehe Hochstufen unsicherer Anfragen.
Lösung
Die Implementierung einer strengen CSP ist der beste Weg, um XSS-Schwachstellen mit CSP zu minimieren. Dies nutzt nonce- oder hash-basierte Abrufdirektiven, um sicherzustellen, dass nur Skripte und/oder Stile ausgeführt werden, die das korrekte Nonce oder den Hash enthalten. JavaScript, das von einem Hacker eingefügt wird, wird einfach nicht ausgeführt.
Strenge CSPs deaktivieren auch:
- Die Nutzung von unsicherem Inline-JavaScript, was inline Event-Handler-Attribute wie
onclick
bedeutet. Dies verhindert, dass unsachgemäß maskierte Benutzereingaben vom Webbrowser als JavaScript interpretiert werden. - Die Nutzung von riskanten API-Aufrufen wie
eval()
, was eine weitere Wirkung derscript-src
-Direktive ist. - Alle Objekt-Einbettungen über
object-src 'none'
. - Die Nutzung des
<base>
-Elements zur Festlegung einer Basis-URI überbase-uri 'none';
.
Strenge CSPs werden bevorzugt gegenüber standortbasierten Richtlinien, auch als Allowlist-Richtlinien bezeichnet, bei denen Sie angeben, von welchen Domains Skripte ausgeführt werden dürfen. Dies liegt daran, dass Allowlist-Richtlinien oft unsichere Domains zulassen, was den gesamten Sinn einer CSP zunichtemacht, und sie können sehr groß und unhandlich werden, insbesondere wenn Sie versuchen, Dienste zu erlauben, die viele Drittanbieter-Skripte erfordern.
Schritte zur Implementierung von CSP
Implementieren Sie eine strenge CSP und beginnen Sie dann, die Ressourcen zu identifizieren, die aufgrund der Richtlinie nicht geladen werden können, und ergreifen Sie Maßnahmen, um diese Probleme zu umgehen.
Hinweis:
Bevor Sie eine tatsächliche CSP mit dem Content-Security-Policy
-Header implementieren, wird empfohlen, diese zuerst mit dem HTTP-Header Content-Security-Policy-Report-Only
zu testen; siehe Nur-Bericht-CSPs unten.
- Entscheiden Sie, ob Sie Nonces oder Hashes verwenden möchten. Sie sollten Nonces verwenden, wenn Sie Inhalte dynamisch generieren können, oder Hashes, wenn Sie statische Inhalte bereitstellen müssen.
- Implementieren Sie eine strenge CSP, wie im Abschnitt Lösung beschrieben. Stellen Sie sicher, dass externe und interne Skripte (eingefügt über
<script>
-Elemente), die Sie ausführen möchten, das korrekte Nonce in dennonce
-Attributen vom Server eingefügt haben. Wenn Sie stattdessen Hashes verwenden, sollten externe Skripte den korrekten Hash in denintegrity
-Attributen haben. - Wenn ein erlaubtes Skript Drittanbieter-Skripte lädt, werden diese Skripte nicht geladen, da sie nicht das erforderliche Nonce oder den Hash haben. Lösen Sie dieses Problem, indem Sie die Direktive
strict-dynamic
hinzufügen, die Skripten, die vom ersten Skript geladen werden, das gleiche Vertrauensniveau verleiht, ohne dass sie ausdrücklich mit einem Nonce oder Hash versehen werden. - Überarbeiten Sie Muster, die von der strengen CSP nicht erlaubt sind, wie z.B. Inline-Event-Handler und
eval()
. Ersetzen Sie beispielsweise Inline-Event-Handler durch Aufrufe vonaddEventListener()
innerhalb von Skripten. - Sofern Sites nicht die Möglichkeit zur Einbettung benötigen, sollte deren Ausführung mit
object-src 'none'
deaktiviert werden. - Wenn Sie die Verwendung von
eval()
nicht entfernen können, können Sie dasunsafe-eval
-Schlüsselwort zu Ihrer strengen CSP hinzufügen, um sie zu erlauben, obwohl dies die CSP erheblich schwächt. - Wenn Sie die Event-Handler-Attribute nicht entfernen können, können Sie das
unsafe-hashes
-Schlüsselwort zu Ihrer strengen CSP hinzufügen, um sie zu erlauben. Dies ist etwas unsicher, aber viel sicherer, als allen Inline-JavaScript zu erlauben.
Wenn Sie es nicht schaffen, eine strenge CSP zum Laufen zu bringen, ist eine auf Allowlist basierende CSP immer noch besser als keine, und eine CSP wie default-src https:
bietet immer noch einen gewissen Schutz, indem unsicheres Inline/eval()
deaktiviert wird und nur das Laden von Ressourcen (Bilder, Schriftarten, Skripte, etc.) über HTTPS erlaubt wird.
Warnung: Wenn möglich, vermeiden Sie es, unsichere Quellen in Ihre CSP aufzunehmen. Zu den Beispielen gehören:
unsafe-inline
.data:
-URIs innerhalb vonscript-src
,object-src
oderdefault-src
.- Zu großzügige Quellen oder Ziele für Formulareinsendungen.
Wenn Sie den Content-Security-Policy
-Header nicht verwenden können, können Seiten stattdessen ein <meta http-equiv="Content-Security-Policy" content="…">
-Element einfügen. Dies sollte das erste <meta>
-Element sein, das innerhalb des Dokuments <head>
erscheint.
Nur-Bericht-CSPs
Bevor Sie eine tatsächliche CSP mit dem Content-Security-Policy
-Header implementieren, wird geraten, diese zuerst mit dem HTTP-Header Content-Security-Policy-Report-Only
zu testen. Dies ermöglicht es Ihnen zu sehen, ob Verstöße mit dieser Richtlinie aufgetreten wären.
Websites sollten die Berichterstattungsrichtlinien report-to
und report-uri
verwenden. Diese veranlassen den Browser, JSON-Berichte über CSP-Verstöße an Endpunkte zu POST
senden (angegeben im Reporting-Endpoints
-Header im Fall von report-to
). Dadurch können CSP-Verstöße schnell erfasst und behoben werden.
Hinweis:
Die Direktive report-to
wird gegenüber der veralteten Direktive report-uri
bevorzugt. Beide werden jedoch noch benötigt, da report-to
noch nicht über vollständige plattformübergreifende Unterstützung verfügt.