Implementierung der Content-Security-Policy (CSP)

Der Content-Security-Policy HTTP-Header bietet eine feingranulare Kontrolle darüber, welcher Code auf einer Website geladen werden kann und welche Aktionen erlaubt sind.

Problem

Das Hauptproblem, auf das sich dieser Artikel konzentriert, sind Cross-Site-Scripting (XSS) Angriffe. Diese entstehen in der Regel aufgrund eines Mangels an Kontrolle und Bewusstsein über die Quellen, von denen Website-Ressourcen geladen werden. Dieses Problem wird schwieriger zu managen, wenn 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 weitere Faktoren, wie z.B. Ausgabe-Codierung und Bereinigung, die ebenfalls wichtig sind.

CSP kann auch helfen, andere Probleme zu beheben, die in anderen Artikeln behandelt werden:

Lösung

Die Implementierung einer strikten CSP ist der beste Weg, um XSS-Schwachstellen mit CSP zu mindern. Dies nutzt nonce- oder hash-basierte Fetch-Richtlinien, um sicherzustellen, dass nur Skripte und/oder Styles, die die korrekte Nonce oder den korrekten Hash enthalten, ausgeführt werden. In JavaScript von Angreifern eingefügte Codes werden einfach nicht ausgeführt.

Strikte CSPs:

  • Deaktivieren die Verwendung von unsicherem Inline-JavaScript, was bedeutet, dass Inline-Event-Handler-Attribute wie onclick nicht verwendet werden. Dies verhindert, dass falsch entschlüsselte Benutzereingaben vom Webbrowser als JavaScript interpretiert werden.
  • Deaktivieren die Verwendung von riskanten API-Aufrufen wie eval(), was ein weiterer Effekt der script-src-Richtlinie ist.
  • Deaktivieren das Einbetten von Objekten über object-src 'none'.
  • Deaktivieren die Verwendung des <base>-Elements zur Festlegung einer Basis-URI über base-uri 'none';.

Strikte CSPs werden gegenüber standortbasierten Richtlinien, auch bekannt als Erlaubnislisten-Richtlinien, bevorzugt, bei denen Sie angeben, von welchen Domains Skripte ausgeführt werden können. Erlaubnislisten-Richtlinien erlauben häufig unsichere Domains, was den gesamten Zweck einer CSP konterkariert. Sie können sehr groß und unhandlich werden, insbesondere wenn Sie versuchen, Dienste zuzulassen, die viele Drittanbieter-Skripte 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 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, sollten Sie diese zuerst mit dem Content-Security-Policy-Report-Only HTTP-Header testen; siehe Nur-Reporting-CSPs unten.

  1. Entscheiden Sie, ob Sie Nonces oder Hashes verwenden. Sie sollten Nonces verwenden, wenn Sie Inhalte dynamisch generieren können, oder 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 (eingeschlossen über <script>-Elemente), die Sie ausführen möchten, die korrekte Nonce in den nonce-Attributen vom Server eingefügt haben. Wenn Sie stattdessen Hashes verwenden, sollten externe Skripte den korrekten Hash in die integrity-Attribute eingefügt haben.
  3. Wenn ein erlaubtes Skript daraufhin Drittanbieter-Skripte lädt, werden diese Skripte nicht geladen, da sie nicht die erforderliche Nonce oder den erforderlichen Hash haben. Lösen Sie dieses Problem, indem Sie die strict-dynamic-Richtlinie hinzufügen, die Skripten, die vom ersten Skript geladen wurden, dasselbe Vertrauensniveau gibt, ohne explizit eine Nonce oder einen Hash zu erhalten.
  4. Überarbeiten Sie Muster, die in der strikten CSP nicht erlaubt sind, wie z.B. Inline-Event-Handler und eval(). Ersetzen Sie beispielsweise Inline-Event-Handler durch addEventListener()-Aufrufe innerhalb von Skripten.
  5. Sofern Websites nicht die Fähigkeit benötigen, Einbindungen zu enthalten, sollten deren Ausführungen 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 zuzulassen, 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 zuzulassen. Dies ist etwas unsicher, aber viel sicherer als die Erlaubnis aller Inline-JavaScripts.

Wenn Sie eine strikte CSP nicht zum Laufen bringen, ist eine erlaubnislistenbasierte CSP viel besser als keine, und eine CSP wie default-src https: bietet immer noch einen gewissen Schutz, bei dem unsicheres Inline/eval() deaktiviert und nur das Laden von Ressourcen (Bilder, Schriftarten, Skripte usw.) über HTTPS zulässt.

Warnung: Vermeiden Sie nach Möglichkeit die Aufnahme unsicherer Quellen in Ihre CSP. Zu den Beispielen gehören:

  • unsafe-inline.
  • data:-URIs innerhalb von script-src, object-src oder default-src.
  • Allzu breite Quellen oder Zielvorgaben für das Absenden von Formularen.

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

Nur-Reporting-CSPs

Bevor Sie eine tatsächliche CSP mit dem Content-Security-Policy-Header implementieren, sollten Sie diese zuerst mit dem Content-Security-Policy-Report-Only HTTP-Header testen. Dies ermöglicht es Ihnen, zu sehen, ob Verstöße gegen diese Richtlinie aufgetreten wären.

Websites sollten die Berichterstattungsrichtlinien report-to und report-uri verwenden. Diese veranlassen den Browser, JSON-Berichte über CSP-Verletzungen an Endpunkte zu POST, die im Header Reporting-Endpoints im Fall von {report-to}/{report-uri} angegeben sind. Dies ermöglicht es, CSP-Verletzungen schnell zu erfassen und zu beheben.

Hinweis: Die report-to-Richtlinie wird gegenüber der veralteten report-uri-Richtlinie bevorzugt. Beide werden jedoch noch benötigt, da report-to noch keine vollständige plattformübergreifende Browserunterstützung hat.

Siehe auch