Implementierung der Content Security Policy (CSP)

Der HTTP-Header Content-Security-Policy bietet eine detaillierte Kontrolle über den Code, der auf einer Website geladen werden kann, und über das, was er tun darf.

Problem

Das Hauptproblem, auf das sich dieser Artikel konzentriert, sind Cross-Site-Scripting- (XSS) Angriffe. Diese sind im Allgemeinen auf einen Mangel an Kontrolle und Bewusstsein über die Quellen zurückzuführen, aus denen Ressourcen einer Website geladen werden. Dieses Problem wird schwieriger zu verwalten, wenn Websites größer und komplexer werden und zunehmend 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 Output Encoding und Sanitization.

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-Sicherheitslücken mit CSP zu minimieren. Dies nutzt auf nonce- oder hash- basierende Fetch-Direktiven, um sicherzustellen, dass nur Skripte und/oder Styles ausgeführt werden, die den richtigen Nonce oder Hash enthalten. Von Hackern eingefügtes JavaScript wird einfach nicht ausgeführt.

Strikte CSPs:

  • Deaktivieren die Nutzung von unsicherem Inline-JavaScript, was inline Ereignis-Handler-Attribute wie onclick bedeutet. Dadurch wird verhindert, dass falsch maskierte Benutzereingaben vom Webbrowser als JavaScript interpretiert werden.
  • Deaktivieren die Nutzung von riskanten API-Aufrufen wie eval(), was ein weiterer Effekt der script-src-Direktive ist.
  • Deaktivieren alle Objekteinbettungen über object-src 'none'.
  • Deaktivieren die Verwendung des <base>-Elements, um eine Basis-URI festzulegen, über base-uri 'none';.

Strikte CSPs sind gegenüber standortbasierten Richtlinien vorzuziehen, die auch als Whitelist-Richtlinien bezeichnet werden, bei denen Sie angeben, von welchen Domains Skripte ausgeführt werden können. Dies liegt daran, dass Whitelist-Richtlinien oft unsichere Domains zulassen, was den gesamten Zweck einer CSP untergräbt, und sie können sehr groß und unhandlich werden, insbesondere wenn Sie versuchen, Dienste zu erlauben, die viele Drittanbieter-Skripte benötigen.

Schritte zur Implementierung einer CSP

Implementieren Sie eine strikte CSP und beginnen Sie dann, Ressourcen zu identifizieren, die aufgrund der Richtlinie nicht geladen werden, 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 Content-Security-Policy-Report-Only-HTTP-Header zu testen; siehe Nur-Bericht-CSPs unten.

  1. 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.
  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, den richtigen Nonce in den vom Server eingefügten nonce-Attributen haben. Wenn Sie stattdessen Hashes verwenden, sollten externe Skripte den richtigen Hash in den integrity-Attributen haben.
  3. Wenn ein erlaubtes Skript dazu übergeht, Drittanbieter-Skripte zu laden, werden diese Skripte nicht geladen, da sie nicht den erforderlichen Nonce oder Hash haben. Umgehen Sie dieses Problem, indem Sie die Direktive strict-dynamic hinzufügen, die Skripten, die vom ersten Skript geladen werden, dasselbe Maß an Vertrauen gibt, ohne dass ihnen explizit ein Nonce oder Hash gegeben werden muss.
  4. Refaktorieren Sie Muster, die von der strikten CSP nicht erlaubt sind, wie Inline-Ereignis-Handler und eval(). Beispielsweise können Sie Inline-Ereignis-Handler durch Aufrufe von addEventListener() in Skripten ersetzen.
  5. Sofern Websites nicht die Möglichkeit benötigen, Einbettungen einzuschließen, sollte deren Ausführung mit object-src 'none' deaktiviert werden.
  6. Wenn Sie die Verwendung von eval() nicht entfernen können, können Sie das Schlüsselwort unsafe-eval Ihrer strikten CSP hinzufügen, um sie zu erlauben, obwohl dies die CSP erheblich schwächt.
  7. Wenn Sie Ereignis-Handler-Attribute nicht entfernen können, können Sie das Schlüsselwort unsafe-hashes Ihrer strikten CSP hinzufügen, um sie zu erlauben. Dies ist etwas unsicher, aber wesentlich sicherer als die Erlaubnis aller Inline-JavaScripts.

Wenn Sie eine strikte CSP nicht zum Laufen bringen können, ist eine auf Whitelists basierende CSP viel besser als keine, und eine CSP wie default-src https: bietet immer noch einen gewissen Schutz, indem unsicheres Inline- und eval() deaktiviert wird und nur das Laden von Ressourcen (Bilder, Schriftarten, Skripte usw.) über HTTPS erlaubt wird.

Warnung: Vermeiden Sie, wenn irgend möglich, das Einbinden unsicherer Quellen in Ihre CSP. Beispiele sind:

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

Ebenso kann die Verwendung von script-src 'self' für Websites mit JSONP-Endpunkten unsicher sein. Diese Websites sollten ein script-src verwenden, das den Pfad zu ihren JavaScript-Quellordnern enthält.

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

Nur-Bericht-CSPs

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

Websites sollten die Reporting-Direktiven report-to und report-uri verwenden. Diese bewirken, dass der Browser JSON-Berichte über CSP-Verstöße an Endpunkte sendet (spezifiziert im Reporting-Endpoints-Header im Falle von report-to). Dies ermöglicht es, CSP-Verstöße schnell zu erkennen und zu beheben.

Hinweis: Die Direktive report-to wird gegenüber der veralteten Direktive report-uri bevorzugt. Beide werden jedoch noch benötigt, da report-to noch keine vollständige Unterstützung über alle Browser hinweg hat.

Siehe auch