Die Reporting-Funktion der Content-Security-Policy (CSP)
CSP hatte ich vor fast 2 Jahren bereits vorgestellt, mittlerweile hat es eine gute Verbreitung gefunden, sodass wir uns nochmals die Details anschauen. CSP ist ein Header, den der Server an den Browser schickt, und darin festlegt, von wo Javascripte, Bilder, CSS, Media-Dateien und mehr geladen werden dürfen. Mit sinnvollen Einstellungen ist es möglich, Cross Site Scripting (XSS) sowie Clickjacking zu verhindern, eine dieser essenziell wichtigen Einstellungen ist das Verbot von Inline-Javascript. Falls also ein Angreifer Javascript beispielsweise in die Datenbank einfügen kann, und bei der Ausgabe nicht oder falsch escaped wird, wird das Inline-Javascript das der Angreifer platziert hat nicht ausgeführt, XSS ist effektiv unterbunden.
In der Apache Konfiguration kann das beispielsweise so aussehen:
<VirtualHost *:80> DocumentRoot /path/to/wwwroot ServerName domain.de Header add X-Content-Security-Policy "allow 'self'; img-src images.domain.de; script-src static.domain.de;" </VirtualHost>
oder hier mittels PHP gesetzt:
<?php header("X-Content-Security-Policy: allow 'self'; img-src images.domain.de; script-src static.domain.de;");
Sollten nun Bilder oder Javascripte eingebunden sein die nicht von den angegebenen Domains kommen wird der Browser sie blockieren und nicht laden. Es gibt neben img-src und script-src auch noch frame-src, xhr-src und weitere.
Wir können nun also alle gültigen Quellen für die externen Ressourcen definieren. Ein hilfreiches Zusatzfeature ist das Reporting, das den Browser anweist, im Falle einer CSP-Verletzung eine bestimmte URL aufzurufen. Es ist auch möglich, nur das Reporting zu aktivieren. Falls also eine unerwartete Ressource geladen wird von einem fremden Server, können wir Alarm schlagen und das Problem analysieren und beseitigen. Ein Reporting-Header sieht beispielsweise so aus:
<?php header("X-Content-Security-Policy-Report-Only: allow 'self'; img-src images.domain.de; script-src static.domain.de; report-uri /violation.php");
Der Header-Name hat sich leicht geändert, eine Reporting-URI ist hinzugekommen, ansonsten ist alles gleich geblieben. Im Unterschied zum normalen Header sorgt der Report-Only-Header dafür dass nichts blockiert wird, nur die Verletzungen werden gemeldet. Ideal falls man nur XSS entdecken möchte, es ist auch hilfreich wenn man gerade den richtigen CSP-Header erstellt und produktiv schaltet, denn man kann beide Header senden, dann wird blockiert und reported. Eigentlich sollte der Reporting-Only Header immer da sein, um Rückmeldungen zu erhalten und auf Bedrohungen reagieren zu können.
Wie sieht nun die violation.php aus?
<?php $json = file_get_contents('php://input'); if ($json === false) { throw new Exception('Bad Request'); } $csp = json_decode($json, true); if (is_null($csp)) { throw new Exception('Bad JSON Violation'); } $msg = "Request: ".$csp['csp-report']['request']."\n". "Request: ".$csp['csp-report']['blocked-uri']."\n". "Request: ".$csp['csp-report']['violated-directive']; // log or mail $msg now
Die Reporting-Informationen kommen als RAW POST JSON Daten. Wir lesen also von der Standard-Eingabe, JSON-decodieren den Text und loggen oder versenden dann die wichtigen Informationen per E-Mail. So sind wir immer auf dem aktuellen Stand bezüglich der CSP-Verstöße.
Hier noch ein Beispiel, und wie es im Firebug dargestellt wird:
<?php header("X-Content-Security-Policy: allow 'self'; img-src images.domain.de; script-src static.domain.de"); header("X-Content-Security-Policy-Report-Only: allow 'self'; img-src images.domain.de; script-src static.domain.de; report-uri /violation.php"); ?> <html> <head> <script type="text/javascript"> alert('CSS'); </script> </head> <body> <img src="https://www.phpgangsta.de/wp-content/uploads/update-300x225.jpg" /> </body> </html>
Die Webseite bleibt komplett weiß, weder das Javascript wird ausgeführt noch das Bild wird angezeigt.
Wäre nur noch interessant welche Browser CSP unterstützen, abgesehen von den Mozialla Produkten.
Alexander K.
30 Aug 11 at 10:15
Eine Übersicht welche Browser die CSP-Header interpretieren würde deinen Artikel noch komplettieren. 😉
Norbert
30 Aug 11 at 10:18
Schade das viele alte Browser die CSP noch nicht unterstützen und daher insbesondere Clickjacking immer noch Tür und Tor geöffnet sind.
Schöner Artikel übrigens wo der Facebook und Google +1 Button in Sachen Security verglichen wird:
http://www.barracudalabs.com/wordpress/index.php/2011/07/21/google-gets-a-1-for-browser-security-3/
Cooler Blog btw. 🙂
Johan
30 Aug 11 at 10:21
Ich suche gerade nochmal, und ich bin überrascht, laut Browserscope kann es nur der Firefox:
http://www.browserscope.org/?category=security&v=top-d
„Nur“ heißt immerhin 55% in Deutschland wenn man StatCounter Glauben schenken darf:
http://gs.statcounter.com/#browser-DE-monthly-201108-201108-bar
Aber ich meine gehört zu haben dass Chrome und Safari auch etwas fertig haben. Hab mich da wohl geirrt.
Michael Kliewe
30 Aug 11 at 14:54
Anscheinend unterstützt die aktuelle Version von Chrome (13) CSP ebenfalls. Safari und Opera sollen bald folgen, die Entwickler von M$ versuchen noch immer zu verstehn was CSP ist und werden es in IE19 (release 2033) vielleicht einbauen 😉
Quelle: http://linux.dashexamples.com/2011/08/adding-content-security-policy-csp-to-apache-virtual-hosts/
Google (Webkit) benutzt aber einen eigenen Header: http://blog.chromium.org/2011/06/new-chromium-security-features-june.html
chris
30 Aug 11 at 17:07
Ich überlege gerade, wenn inline Javascript verboten ist, wie man den JS-Dateien am besten sich änderne Variablen definiert… Bis jetzt habe ich das über JS-Konstanten gelöst. Als erste alternative würde ich es über Input:hidden lösen. Der Nachteil wäre aber, der Benutzer kann das Feld leichter manipulieren… Fällt euch ein praktische Lösung ein oder ist die „Manipulationsgefahr“ die ich sehe belanglos?
Kettil
2 Sep 11 at 09:36
@Kettil: Schau dir mal für solche „Variablen an Javascript“ das HTML var-Tag an, das ist für Variablen gedacht:
http://www.quackit.com/html/tags/html_var_tag.cfm
<var id=“app_width“>126</var>
Über CSS kann man die var-Tags unsichtbar machen (standardmäßig ist der Inhalt sichtbar), und man kann auch, nachdem man die Variable eingelesen hat mittels Javascript, das HTML-Element aus dem DOM löschen.
Michael Kliewe
2 Sep 11 at 10:08
[…] Cross Side Scripting verbieten. Eine Möglichkeit Cross Side Scripting effektiv zu unterbinden. Wenn Persistant Cross Side Scripts von externen Quellen geladen werden, kann eine Meldung an den Webmaster gesendet werden. Zur Information: Ich benutze kein automatisches Tool um eine Schwachstelle zu finden. Das ist gute, alte Handarbeit und etwas Gespür. […]
Forschung: Sicherheit öffentlicher Web-Anwendungen.
11 Nov 11 at 14:45
report-uri
ist auch beiContent-Security-Policy
erlaubt und nicht aufContent-Security-Policy-Report-Only
beschränkt. In diesem Fall werden externe Ressourcen geblockt und zusätzlich gemeldet.Die experimentellen Header
X-Content-Security-Policy
undX-WebKit-CSP
sind inzwischen Geschichte. Der offizielle Standard heißt jetztContent-Security-Policy
und wird zumindest schon von Chrome und Firefox unterstützt.Martin Melcher
26 Nov 13 at 08:54
Die experimentellen Header braucht man aktuell wohl schon noch in verschiedenen Browsern:
http://caniuse.com/#feat=contentsecuritypolicy
Markus
26 Nov 13 at 22:27
Hallo,
was kann ich machen?
Bin gerade dabei meine erste Webseite zu erstellen und erhalte nun diese Meldung.
Brauche Hilfe – habe keine Ahnung von so Sachen.
Blockiert von der Inhaltsicherheitsrichtlinie (CSP)
Diese Webseite hat eine Inhaltsicherheitsrichtlinie (Content Security Policy), die verhindert, dass die Webseite auf diese Weise eingebunden wird.
Firefox hat diese Webseite daran gehindert, auf diese Weise geladen zu werden, weil die Webseite eine Inhaltsicherheitsrichtlinie (Content Security Policy) hat, die dies nicht erlaubt.
Kann man da überhaupt was machen?
Liebe Grüße Ewald
Ewald
20 Jan 17 at 20:34