Implementierung der Content Security Policy (CSP)

Der HTTP-Header Content-Security-Policy bietet eine feingranulare Kontrolle über den Code, der auf einer Webseite geladen werden kann, und was damit gemacht werden darf.

Problem

Das Hauptproblem, auf das sich dieser Artikel konzentriert, sind Cross-Site Scripting (XSS) Angriffe. Diese sind im Allgemeinen auf mangelnde Kontrolle und unzureichendes Bewusstsein für die Quellen zurückzuführen, von denen Ressourcen einer Website geladen werden. Dieses Problem wird schwieriger zu verwalten, da Websites größer und komplexer werden und zunehmend auf Ressourcen Dritter wie JavaScript-Bibliotheken angewiesen sind.

Hinweis: CSP ist ein Teil einer vollständigen Strategie zum Schutz vor XSS-Angriffen. Es gibt noch andere Faktoren, die berücksichtigt werden müssen, wie z. B. Ausgabe-Encoding und Bereinigung, die ebenfalls wichtig sind.

CSP kann auch helfen, andere Probleme zu lösen, die in anderen Artikeln behandelt werden:

Lösung

Die Implementierung einer strikten CSP ist der beste Weg, um XSS-Sicherheitslücken mit CSP zu mildern. Dazu werden auf nonce- oder hash- basierende Abrufdirektiven verwendet, um sicherzustellen, dass nur Skripte und/oder Stile ausgeführt werden, die die korrekte Nonce oder Hash enthalten. Von einem Hacker eingebrachter JavaScript-Code läuft einfach nicht.

Strikte CSPs:

  • Deaktivieren die Verwendung von unsicherem inline JavaScript, was bedeutet, dass Inline-Event-Handler-Attribute wie onclick nicht verwendet werden dürfen. Dies verhindert, dass falsch maskierte Benutzereingaben vom Webbrowser als JavaScript interpretiert werden.
  • Deaktivieren die Nutzung von riskanten API-Aufrufen wie eval(), was ebenfalls eine Wirkung der script-src Direktive ist.
  • Deaktivieren alle Objekteinbettungen über object-src 'none'.
  • Deaktivieren die Verwendung des <base> Elements zur Festlegung eines Basis-URIs über base-uri 'none';.

Strikte CSPs sind gegenüber ortsabhängigen Richtlinien (auch als Positivlisten-Richtlinien bekannt) bevorzugt, bei denen Sie angeben, von welchen Domains Skripte ausgeführt werden können. Das liegt daran, dass Positivlisten-Richtlinien oft unsichere Domains zulassen, was den gesamten Zweck einer CSP zunichte macht. Sie können auch sehr groß und unhandlich werden, insbesondere wenn Sie Dienste erlauben möchten, die viele Drittanbieterskripte erfordern.

Schritte zur Implementierung von CSP

Implementieren Sie eine strikte CSP und beginnen Sie dann, Ressourcen zu identifizieren, die aufgrund der Richtlinie nicht geladen werden, um Möglichkeiten zu finden, diese Probleme zu umgehen.

Hinweis: Bevor Sie eine tatsächliche CSP mit dem Content-Security-Policy Header implementieren, wird empfohlen, sie zunächst mit dem HTTP-Header Content-Security-Policy-Report-Only zu testen. Siehe Nur-Berichte-CSPs unten.

  1. Entscheiden Sie, ob Sie Nonces oder Hashes verwenden möchten. Nonces sollten verwendet werden, wenn Sie Inhalte dynamisch generieren können, Hashes, wenn Sie statische Inhalte bereitstellen müssen.
  2. Implementieren Sie eine strikte CSP, wie im Abschnitt Lösung beschrieben. Stellen Sie sicher, dass externe und interne Skripte (eingebunden über <script> Elemente), die Sie ausführen möchten, die korrekte Nonce vom Server in die nonce Attribute eingefügt bekommen. Wenn Sie stattdessen Hashes verwenden, sollten externe Skripte den korrekten Hash in integrity Attribute eingefügt haben.
  3. Wenn ein erlaubtes Skript weiter Drittanbieterskripte lädt, schlagen diese fehl, da sie die erforderliche Nonce oder Hash nicht haben. Mildern Sie dieses Problem, indem Sie die strict-dynamic Direktive hinzufügen, die Skripten, die vom ersten Skript geladen werden, das gleiche Vertrauensniveau gibt, ohne explizit eine Nonce oder Hash zu benötigen.
  4. Überarbeiten Sie Muster, die durch die strikte CSP nicht erlaubt sind, wie Inline-Event-Handler und eval(). Ersetzen Sie beispielsweise Inline-Event-Handler durch Aufrufe von addEventListener() innerhalb von Skripten.
  5. Sofern Websites die Möglichkeit, Einbettungen einzuschließen, nicht benötigen, sollte ihre Ausführung mit object-src 'none' deaktiviert werden.
  6. Wenn Sie die Verwendung von eval() nicht entfernen können, können Sie das unsafe-eval Schlüsselwort zu Ihrer strikten CSP hinzufügen, um sie zu erlauben, obwohl dies die CSP erheblich schwächt.
  7. Wenn Sie die Event-Handler-Attribute nicht entfernen können, können Sie das unsafe-hashes Schlüsselwort zu Ihrer strikten CSP hinzufügen, um sie zu erlauben. Dies ist etwas unsicher, aber wesentlich sicherer, als alle Inline-JavaScripts zuzulassen.

Wenn es Ihnen nicht gelingt, eine strikte CSP zum Laufen zu bringen, ist eine auf Positivlisten basierende CSP viel besser als keine, und eine CSP wie default-src https: bietet immer noch etwas Schutz, indem sie unsichere Inline/eval() deaktiviert und nur das Laden von Ressourcen (Bilder, Schriftarten, Skripte usw.) über HTTPS erlaubt.

Warnung: Vermeiden Sie es nach Möglichkeit, unsichere Quellen in Ihre CSP aufzunehmen. Beispiele sind:

  • unsafe-inline.
  • data: URIs innerhalb von script-src, object-src, oder default-src.
  • Zu breite Quellen oder Zielorte für Formulareinreichungen.

Wenn Sie den Content-Security-Policy Header nicht verwenden können, können Seiten stattdessen ein <meta http-equiv="Content-Security-Policy" content="…"> Element enthalten. Dies sollte das erste <meta> Element sein, das innerhalb des Dokuments im <head> erscheint.

Nur-Berichte-CSPs

Bevor Sie eine tatsächliche CSP mit dem Content-Security-Policy Header implementieren, wird empfohlen, sie zunächst mit dem HTTP-Header Content-Security-Policy-Report-Only zu testen. Dadurch können Sie sehen, ob es mit dieser Richtlinie zu Verstößen gekommen wäre.

Webseiten sollten die Berichtsdirektiven report-to und report-uri verwenden. Diese veranlassen den Browser, JSON-Berichte über CSP-Verstöße an Endpunkte zu senden (wie im Reporting-Endpoints Header im Fall von report-to angegeben). Dadurch können CSP-Verstöße schnell erkannt und behoben werden.

Hinweis: Die report-to Direktive wird der veralteten report-uri Direktive vorgezogen. Beide werden jedoch noch benötigt, da report-to noch keine vollständige Unterstützung in allen Browsern hat.

Siehe auch