Sicherheit/Content Security Policy
Die Hersteller der Browser und auch die Webstandards entwickelnden Gremien sind ständig darum bemüht, Mechanismen zu finden, mit denen Angriffe auf Seitenbesucher verhindert werden können. Es geht insbesondere darum, das Unterschieben von bösartigem Code abzuwehren. Bei den sogenannten Cross-Site-Scripting-Attacken werden Daten von fremden Webservern eingebunden, die die Aufgabe haben, den Datenverkehr auf der gerade besuchten Website auszuspionieren, diesen zu manipulieren oder gar mögliche Softwarefehler auf dem Rechner des Seitenbesuchers auszunutzen, um Schadsoftware zu installieren.
Ein solcher Abwehrmechanismus ist die Content Security Policy (zu deutsch etwa „Richtlinie für die Sicherheit der Inhalte“). Die Idee dahinter ist, dass der Webserver beim Ausliefern der eigentlichen Webseite noch zusätzliche Meta-Daten übermittelt, die den Browser dazu veranlassen, verschiedene Vorgänge zu verhindern. So ist es damit beispielsweise möglich, dass der Browser keine JavaScript-Dateien lädt und ausführt, wenn diese nicht von exakt demselben Webserver stammen, von dem die eigentliche Seite geladen wurde. Es kann sehr fein abgestuft werden, ob das JavaScript in einer eigenen Datei notiert sein muss, oder ob direkt im HTML-Dokument notierter JavaScript-Code, der in <script>
-Elemente eingebettet ist, ausgeführt werden darf.
Inhaltsverzeichnis
Der CSP-Header
Beim Ausliefern des HTML-Dokuments bedarf es eines speziellen HTTP-Headers, der den Browser die Content Security Policy anwenden lässt. Dazu gibt es mehrere Möglichkeiten:
-
<meta>
-Element im HTML-Code - serverseitige Scriptsprache
- Konfiguration des Webservers
Historisch
Vor der vollständigen Unterstützung nutzten Browser die experimentellen Header:
- Internet Explorer und Firefox
X-Content-Security-Policy
- Chrome und Safari
X-WebKit-CSP
Diese Browser unterstützen seit 2013 den standardisierten Header bzw. sind nicht mehr auf dem Markt. Sie können daher in Ihrer Website auf die experimentellen Header verzichten.
<meta>
-Element im HTML-Code
Wenn kein CSP-Header vom Server versandt wird, kann man mit einem passenden <meta>
-Element nachhelfen. Sollte der Server irgendwann doch einen CSP-Header senden, hat dieser – wie in solchen Fällen üblich – für den Browser Vorrang vor dem <meta>
-Element.
<meta>
-Element im HTML-Code
<!doctype html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>CSP nutzende Seite</title>
</head>
<body>
<h1>Sie sind sicher</h1>
<p>Dieses Dokument wurde mit einer sehr strikt eingestellten Content Security Policy ausgeliefert.</p>
</body>
</html>
serverseitige Scriptsprache
<?php
header("Content-Security-Policy: default-src 'self'; script-src 'self'");
header()
, um einen HTTP-Header an den Browser zu senden.Konfiguration des Webservers
Wenn man seinen eigenen Webserver konfigurieren kann, was bei günstigen Hostingangeboten in aller Regel nicht der Fall ist, dann gibt es diese Einstellungsmöglichkeit:
Header set Content-Security-Policy "default-src 'self';"
server {
...
add_header Content-Security-Policy "default-src 'self';";
}
Einstellungsmöglichkeiten
Die CSP bringt eine ganze Reihe an Parametern mit, mit denen sich das Browserverhalten sehr fein einstellen lässt.
Direktive | Beispielwert | Erläuterung |
---|---|---|
default-src |
'self' cdn.example.com |
Die Direktive default-src ist die Voreinstellung für alle Richtlinien, die weitere Inhalte nachladen wie z. B. JavaScript, Bilder, CSS, Schriftarten, AJAX Requests, Frames und HTML5 Medien. In der Referenz der Werteangaben steht genaueres über die möglichen Werte, die Sie hier anstelle von 'self' verwenden können.
|
script-src |
'self' js.example.com |
Definiert erlaubte Quellen für JavaScript. |
style-src |
'self' css.example.com |
Definiert erlaubte Quellen für Stylesheets. |
img-src |
'self' img.example.com |
Definiert erlaubte Quellen für Bilder. |
connect-src |
'self' |
Gilt für XMLHttpRequests (AJAX), WebSockets oder EventSource. Wenn solche Inhalte nicht erlaubt sein sollen, wird der Browser beim Laden der Seite einen 400 HTTP Status Code emulieren. |
font-src |
font.example.com | Definiert erlaubte Quellen für Schriftarten. |
object-src |
'self' |
Definiert erlaubte Quellen für Plugins, z. B. <object> , <embed> oder <applet> .
|
media-src |
media.example.com | Definiert erlaubte Quellen für Audio und Video, z. B. HTML5 <audio> , <video> Elemente.
|
sandbox |
allow-forms allow-scripts |
Ermöglicht einen Sandbox-Betrieb für die angeforderte Ressource, ähnlich wie <iframe sandbox> . Im Sandbox-Betrieb gilt eine Same-Origin-Policy, Popups werden verhindert und Plugins und das Ausführen von JavaScript werden blockiert. Sie können den Wert für sandbox leer lassen, um alle Einschränkungen zu belassen, oder Sie fügen eine dieser Wertegruppen hinzu: allow-forms allow-same-origin allow-scripts allow-popups , allow-modals , allow-orientation-lock , allow-pointer-lock , allow-presentation , allow-popups-to-escape-sandbox , und allow-top-navigation
|
report-uri |
/pfad-zu-server-script | Diese Direktive weist den Browser an, Berichte über an Richtlinien gescheiterte Vorgänge mittels der POST-Methode an die angegebene Adresse zu senden. Sie können den Zusatz -Report-Only an den HTTP-Headernamen anhängen, um den Browser anzuweisen, dass er lediglich Berichte sendet aber keine Inhalte blockt.
|
child-src |
'self' |
Definiert erlaubte Quellen für Webworkers und verschachtelte Browsing-Contexte bei Elementen wie <frame> und <iframe> .
|
form-action |
'self' |
Definiert erlaubte Ziele für HTML Formulare. |
frame-ancestors |
'none' |
Definiert erlaubte Quellen, die eingebettete Inhalte haben dürfen, wie z. B. bei <frame> , <iframe> , <object> , <embed> und <applet> . Wenn man diese Direktive auf 'none' setzt, sollte das ungefähr die gleiche Wirkung haben wie der Header X-Frame-Options: DENY .
|
plugin-types |
application/pdf |
Definiert erlaubte MIME-Typen für Plugins, die über <object> und <embed> vom Browser gestartet werden. Um ein <applet> laden zu lassen, müssen Sie den Wert application/x-java-applet angeben.
|
Referenz der Werteangaben
Alle diejenigen Direktiven, die auf -src
enden, können ähnliche Werte als eine Liste von Quellen aufnehmen. Mit Ausnahme des Wertes 'none'
, der grundsätzlich als alleiniger Wert in einer Direktive stehen muss, können mehrfache Quellen durch Leerzeichen getrennt notiert werden.
Quellenangabe | Beispiel | Erläuterung |
---|---|---|
* |
img-src * |
Wildcard, erlaubt jegliche URL mit Ausnahme von data: , blob: , filesystem: und schemes: .
|
'none' |
object-src 'none' |
Verhindert das Laden von Ressourcen von egal welcher Quelle. |
'self' |
script-src 'self' |
Erlaubt das Laden von Ressourcen von dem selben Ursprung (gleiches Schema wie https:// , Server und Port).
|
data: |
img-src 'self' data: |
Erlaubt das Laden von Ressourcen über das data: -Schema (z. B. base64-kodierte Bilder).
|
blob: |
worker-src 'self' blob: |
Erlaubt das Laden von Binärblobs über das blob: -Schema (z. B. Blobs, die Teile eines Video-Streams enthalten).
|
domain.example.com |
img-src domain.example.com |
Erlaubt das Laden von Ressourcen von der Domain mit dem angegebenen Namen. |
*.example.com |
img-src *.example.com |
Erlaubt das Laden von Ressourcen von jeder Subdomain unter example.com. |
https://cdn.com |
img-src https://cdn.com |
Erlaubt das Laden von Ressourcen ausschließlich mit HTTPS von der angegebenen Domain. |
https: |
img-src https: |
Erlaubt das Laden von Ressourcen ausschließlich mit HTTPS von jeglicher Domain. |
'unsafe-inline' |
script-src 'unsafe-inline' |
Erlaubt die Benutzung von inline-Code wie z. B. style -Attribute, Eventhandler-Attribute wie onclick und in <script> -Elementen notierter JavaScript-Code
|
'unsafe-eval' |
script-src 'unsafe-eval' |
Erlaubt unsichere dynamische Code-Auswertung wie z. B. die JavaScript-Methode eval() .
|
'nonce-xxxx' |
script-src 'nonce-r@nd0m' |
Erlaubt die Ausführung eines Scripts nur, wenn es über ein Script-Element geladen wurde, dessen nonce-Attribut den Wert 'r@nd0m' hat. Entsprechendes gilt für style-src. An Stelle von 'r@nd0m' sollte natürlich eine kryptographisch sichere Zufallszahl verwendet werden, und sie muss für jede Auslieferung der Seite neu bestimmt werden.]]. |
HTTPS sollte längst Pflicht sein
Wenn eine Seite unverschlüsselt zum Benutzer gesendet wird, ist der Datenverkehr für alle zwischengeschalteten Instanzen einsehbar. Daher ist es unbedingt zu empfehlen, den HTTP-Datenstrom zu verschlüsseln. Dazu benötigt der Webserver ein SSL-Zertifikat. Diese sind in der Regel kostenpflichtig, aber seit Mozilla die Initiative "Let's encrypt!" ins Leben gerufen hat, sind solche Zertifikate inzwischen je nach Hostingpartner auch kostenlos verfügbar.
In den CSP-Direktiven lässt sich die Verwendung von HTTPS jedenfalls erzwingen.
Weblinks
- Wikipedia: Content Security Policy
- Mozilla: Content Security Policy
- Mozilla: https://observatory.mozilla.org/ (Webdienst zum Testen der eigenen Seite)
- https://content-security-policy.com/
- https://letsencrypt.org/
- Content Security Policy 1.0: https://www.w3.org/TR/CSP1/
- Content Security Policy Level 2: https://www.w3.org/TR/CSP2/
- Content Security Policy Level 3: https://www.w3.org/TR/CSP3/
- Report URI: https://report-uri.com/home/tools (Verschiedene CSP Tools, Betreiber bietet Report-Endpunkt an)
<meta>
-Element notiert, welches den Browser erkennen lässt, dass er das Sicherheitskonzept anwenden soll. Die Anweisung default-src 'self' bedeutet, dass er prinzipiell nur zusätzliche Inhalte laden darf, wenn sie vom selben Server stammen. Die Anweisung script-src 'self' imcontent
-Attribut erklärt dem Browser, dass er nur JavaScript-Dateien laden darf, die vom selben Server stammen wie dieses Dokument.Diese Direktive hat eine zusätzliche Auswirkung: Der Browser darf keinen JavaScript-Code ausführen, der im HTML-Dokument selbst notiert ist. Soll JavaScript ausgeführt werden, so muss es in einer separaten Datei notiert stehen.