CSP-Generator

Nennen Sie uns die Adresse einer echten Seite. Wir lesen ihr HTML, listen jede Quelle auf, aus der sie Skripte, Styles, Bilder, Schriften und Frames lädt, und schreiben eine Richtlinie, die Sie im Report-Only-Modus testen können, wo sie nichts kaputt machen kann.

Wählen Sie eine typische Seite, nicht nur die Startseite: eine Produktseite, einen Artikel, das Kontaktformular. Jede kann aus anderen Quellen laden.

Oder probieren Sie github.com, wordpress.org, www.bbc.com

Eine Gästeliste für Ihre eigenen Seiten

Ein Browser tut, was eine Seite ihm sagt. Steht im HTML „führe dieses Skript von jenem Server aus“, dann führt er es aus. Gefährlich wird das an dem Tag, an dem jemand anderes eine Zeile in Ihre Seite schmuggelt, über ein ungefiltertes Kommentarfeld, ein kompromittiertes Plugin oder eine Werbeanzeige. Der Browser kann seine Zeile nicht von Ihrer unterscheiden.

Eine Content-Security-Policy (CSP) ist ein Antwort-Header, mit dem Sie dem Browser vorab sagen, woher diese Seite etwas laden darf. Sie liest sich wie eine Gästeliste, mit einer Zeile pro Art von Ressource:

default-src 'self';
script-src 'self' https://cdn.example.com;
img-src 'self' data: https://images.example.net;
object-src 'none'

Jede Zeile ist eine Direktive. 'self' bedeutet die eigene Origin der Seite. Alles, was nicht auf der Liste steht, wird abgewiesen, und die Abweisung erscheint in der Browserkonsole.

Wie diese Seite den Entwurf erstellt

Unser Server ruft die Adresse einmal ab und zerlegt das HTML so, wie ein Browser es täte, ohne etwas davon auszuführen. Jede gefundene Adresse wird auf ihre Origin gekürzt (Schema und Host, ohne Pfad) und einsortiert:

DirektiveGelesen aus
script-src<script src>, Modul-Preloads und Skriptadressen, die in Inline-Ladeskripten genannt werden
style-srcStylesheet-Links und @import-Regeln
img-src, font-srcBild-Tags, srcset, Icons, Poster, Preloads und url() in Inline-CSS und in den ersten vier Stylesheets der eigenen Origin der Website
frame-src, media-src, object-src, manifest-srcFrames, Audio und Video, Plugins, der Manifest-Link
form-action, base-uriFormularziele und das <base>-Tag
connect-srcnur Preconnect-Hinweise und die dokumentierten Endpunkte einiger auf der Seite gefundener Dienste (Google Analytics, Google Fonts, Cloudflare Web Analytics)

Der Entwurf beginnt mit default-src 'self', fügt eine Zeile pro Direktive hinzu und schließt die Türen, die keinen Fallback haben: object-src 'none', base-uri 'self', frame-ancestors 'self', dazu upgrade-insecure-requests auf HTTPS-Seiten. Sendet die Seite bereits eine Richtlinie, im Header oder in einem Meta-Tag, zeigen wir sie an und vergleichen sie mit dem, was die Seite lädt.

Der schwierige Teil: Inline-Code

Eingeschleuster Code ist fast immer inline, als <script>-Block oder als onclick-Attribut direkt in der Seite. Eine Richtlinie, die etwas taugt, verbietet also Inline-Code. Der Haken: Die meisten Websites haben selbst reichlich davon. Das Werkzeug zählt Skriptblöcke, Event-Handler-Attribute, javascript:-Links, Style-Blöcke und style=-Attribute und liefert Ihnen dann zwei Entwürfe.

  • Der strenge Entwurf enthält kein 'unsafe-inline'. Dort wollen Sie hin, und er würde den oben gezählten Inline-Code blockieren.
  • Der Übergangsentwurf fügt 'unsafe-inline' dort hinzu, wo die Seite es braucht. Er begrenzt weiterhin, von welchen Websites geladen werden darf, hält aber eingeschleuste Inline-Skripte nicht mehr auf, deshalb ist er als schwach markiert.

Vom einen zum anderen kommen Sie auf drei Wegen. Verschieben Sie den Code in Dateien, lassen Sie den Server jedes Tag mit einer Nonce pro Antwort versehen, oder führen Sie den SHA-256-Hash jedes Blocks in der Richtlinie auf. Das Werkzeug berechnet diese Hashes für die gefundenen Skriptblöcke. Sie helfen nur bei Blöcken, deren Text sich nie ändert.

Immer zuerst Report-Only

Senden Sie den Entwurf als Content-Security-Policy-Report-Only. Der Browser erzwingt nichts und protokolliert, was er blockiert hätte. Gehen Sie mit offener Konsole durch die Website, ergänzen Sie, was berechtigterweise fehlt, und wiederholen Sie das, bis das Protokoll ruhig bleibt. Dann benennen Sie den Header in Content-Security-Policy um. Sie erhalten Snippets für Apache, nginx und ein Meta-Tag. Die Meta-Variante kann weder Report-Only noch frame-ancestors.

Der Entwurf stammt von einer Seite, einmal gelesen, ohne dass etwas ausgeführt wurde. Er sieht weder die Anfragen, die Skripte nach dem Laden stellen (Analytics-Beacons, Chat-Widgets, Zahlungsframes, nachgeladene Bilder), noch was angemeldete Besucher bekommen, noch andere Seiten der Website. Rechnen Sie damit, Quellen ergänzen zu müssen. Für eine Bewertung der Header, die eine Seite heute sendet, nutzen Sie die Bewertung der Sicherheits-Header.

Häufige Fragen

Macht eine Content-Security-Policy meine Website kaputt?

Eine erzwungene Richtlinie blockiert alles, was sie nicht aufführt, eine falsche also schon. Eine Report-Only-Richtlinie kann nichts kaputt machen, weil sie nur protokolliert. Fangen Sie dort an und schalten Sie auf Erzwingen um, sobald die Konsole auf Ihren wichtigsten Seiten keinen Verstoß mehr zeigt.

Lohnt sich eine Richtlinie mit unsafe-inline?

Teilweise. Sie begrenzt weiterhin, wohin Skripte, Frames und Formulare gehen dürfen, blockiert Plugins und verhindert das Kapern über das <base>-Tag. Einen Angreifer, der einen Skriptblock in die Seite schreiben kann, hält sie nicht auf, und genau dafür hat man eine Richtlinie. Nutzen Sie sie als Zwischenschritt.

Was ist der Unterschied zwischen einer Nonce und einem Hash?

Eine Nonce ist ein Zufallswert, den der Server für jede Antwort erzeugt und an jedem Skript-Tag wiederholt, dem er vertraut. Ein Hash ist der Fingerabdruck eines bestimmten Codeblocks, aufgeführt in der Richtlinie. Nonces passen zu Seiten, die bei jeder Anfrage neu gebaut werden. Hashes passen zu wenigen statischen Snippets auf Seiten, die gecacht werden können.

Warum fehlen Pfade in der erzeugten Richtlinie?

CSP erlaubt Pfade wie https://cdn.example.com/lib/, aber sie werden nach einer Weiterleitung ignoriert und gehen kaputt, sobald eine Datei verschoben wird. Die meisten eingesetzten Richtlinien führen Origins auf. Hostet eine Origin Dateien vieler Anbieter, etwa ein öffentliches CDN, sichern Sie die genauen Dateien zusätzlich mit Integritäts-Hashes ab.

Kann ich eine CSP in WordPress oder einem anderen CMS setzen?

Ja, über die Webserver-Konfiguration oder ein Sicherheits-Plugin, das Header sendet. Theme und Plugins bringen eine lange Liste von Inline-Skripten und Styles mit, beginnen Sie also mit dem Report-Only-Header und dem Übergangsentwurf und bauen Sie dann den Inline-Code Plugin für Plugin ab.

Wo sehe ich, was die Richtlinie blockiert?

Im Tab „Konsole“ der Entwicklertools des Browsers. Jeder Verstoß nennt die Direktive und die blockierte Adresse. Um sie von Besuchern zu sammeln, fügen Sie eine Direktive report-uri oder report-to hinzu, die auf einen Sammeldienst zeigt.