PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


Die Reporting-Funktion der Content-Security-Policy (CSP)

with 10 comments

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="http://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.

Written by Michael Kliewe

August 30th, 2011 at 8:52 am

10 Responses to 'Die Reporting-Funktion der Content-Security-Policy (CSP)'

Subscribe to comments with RSS or TrackBack to 'Die Reporting-Funktion der Content-Security-Policy (CSP)'.

  1. Wäre nur noch interessant welche Browser CSP unterstützen, abgesehen von den Mozialla Produkten.

    Alexander K.

    30 Aug 11 at 10:15

  2. Eine Übersicht welche Browser die CSP-Header interpretieren würde deinen Artikel noch komplettieren. ;)

    Norbert

    30 Aug 11 at 10:18

  3. 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

  4. 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

  5. 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

  6. 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

  7. @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

  8. [...] 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. [...]

  9. report-uri ist auch bei Content-Security-Policy erlaubt und nicht auf Content-Security-Policy-Report-Only beschränkt. In diesem Fall werden externe Ressourcen geblockt und zusätzlich gemeldet.

    Die experimentellen Header X-Content-Security-Policy und X-WebKit-CSP sind inzwischen Geschichte. Der offizielle Standard heißt jetzt Content-Security-Policy und wird zumindest schon von Chrome und Firefox unterstützt.

    Martin Melcher

    26 Nov 13 at 08:54

  10. Die experimentellen Header braucht man aktuell wohl schon noch in verschiedenen Browsern:

    http://caniuse.com/#feat=contentsecuritypolicy

    Markus

    26 Nov 13 at 22:27

Leave a Reply

You can add images to your comment by clicking here.