Christian Kruse: Content-Security-Policy mit script-src hash funktioniert nicht wie erwartet

problematische Seite

Hallo alle,

ich spiele gerade (zum Zwecke der Weiterbildung) mit Content-Security-Policy-Headern herum. Im Grunde ist das ja kein Hexenwerk, jedoch bin ich da auf ein Problem gestoßen. Gegeben sei folgendes Inline-Script, dass ich in einem onload notiere:

    <link rel="stylesheet" href="/css/font-da5c620f50bea52c7f4bce090827ebc1.css?vsn=d" media="none" onload="if(media!='all')media='all'">

Ich lade damit (non-blocking) einen Font nach. Nun führe ich folgenden Header ein:

Content-Security-Policy: default-src 'none'; script-src 'sha256-eTuulTlJnm4CGH/rvS4g/RfdQCYAM/UXXb/C8pREDZo='; img-src 'self'; style-src 'self'; object-src 'none'

Damit sollten meinem Verständnis nach alle Scripte außer dem einen Inline-Handler verboten werden. Dummerweise wird aber das Script in dem Handler auch nicht erlaubt, Chrome sagt mir:

Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src 'sha256-eTuulTlJnm4CGH/rvS4g/RfdQCYAM/UXXb/C8pREDZo='". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.

Der Firefox sagt ähnliches:

Content Security Policy: Die Einstellungen der Seite haben das Laden einer Ressource auf self blockiert ("script-src 'sha256-eTuulTlJnm4CGH/rvS4g/RfdQCYAM/UXXb/C8pREDZo='"). Source: onload attribute on LINK element.

Zuerst dachte ich, dass die SHA256-Summe falsch ist, aber die ist definitiv richtig:

echo -n "if(media!='all')media='all'" | openssl dgst -sha256 -binary | base64
eTuulTlJnm4CGH/rvS4g/RfdQCYAM/UXXb/C8pREDZo=

Hat jemand eine Idee, was ich hier falsch mache?

Edit: ich hab das mal auf WWWTech.de online gestellt.

Edit 2: Ich habe natürlich auch ausprobiert die Prüfsumme Hex-codiert anzugeben. Das geht auch nicht.

LG,
CK

  1. problematische Seite

    Hallo,

    gut, sieht so aus als sei das bisher nicht vorgesehen gewesen. Man muss zusätzlich unsafe-hashed-attributes notieren; das wird aber wohl noch nicht unterstützt von gängigen Browsern. Also doch ein externes Script oder ein Script-Block.

    LG,
    CK

  2. problematische Seite

    Lieber Christian,

    Content-Security-Policy-Headern

    ja, da war ich neulich auch mit unterwegs.

    Gegeben sei folgendes Inline-Script, dass ich in einem onload notiere:

    Wer strenge CSP-Settings nutzen möchte, muss jeglichen JS-Code in eine extern zu ladende Script-Datei stecken. Sonst blockt der Browser. Und das sollte ja auch keine übergroße Anstrengung sein, mal eben dynamisch das Element zu ermitteln, um dann damit genau das zu tun, was man vorher mit einem Eventhandler zu erreichen suchte...

    Ob Deine Lösung mit einem Hash "besser" gewesen wäre, vermag ich nicht zu beurteilen, aber wenn ich via CSP irgendein onload blocken will, dann eben alle und ohne Ausnahme!

    Liebe Grüße,

    Felix Riesterer.

    1. problematische Seite

      Hallo Felix,

      Gegeben sei folgendes Inline-Script, dass ich in einem onload notiere:

      Wer strenge CSP-Settings nutzen möchte, muss jeglichen JS-Code in eine extern zu ladende Script-Datei stecken. Sonst blockt der Browser.

      Nein, das stimmt nicht. nonce- und sha...- existieren und funktionieren. Nur eben (noch) nicht für Event-Handler.

      Und das sollte ja auch keine übergroße Anstrengung sein, mal eben dynamisch das Element zu ermitteln, um dann damit genau das zu tun, was man vorher mit einem Eventhandler zu erreichen suchte...

      Ich schrieb mit voller Absicht dazu, dass es mir um den Lern-Effekt ging. Wie ich das umbauen kann, dass es funktioniert, wusste ich schon vorher. Ich wollte verstehen, was ich falsch mache. Ich glaube, dass ich das auch genau so geschrieben habe 😀

      Ob Deine Lösung mit einem Hash "besser" gewesen wäre, vermag ich nicht zu beurteilen, aber wenn ich via CSP irgendein onload blocken will, dann eben alle und ohne Ausnahme!

      Wie gesagt, das ist nicht richtig. Der CSP-Draft für unsafe-hashed-attributes existiert, die Umsetzung existiert zumindest für Chrome auch schon (der Patch ist bereits in Master) und ich konnte es inzwischen mit einem selbst kompilierten Chromium verifizieren, aber es ist noch nicht released.

      LG,
      CK

      1. problematische Seite

        Lieber Christian,

        Ich schrieb mit voller Absicht dazu, dass es mir um den Lern-Effekt ging.

        mir ging es um die Frage, ob man das tatsächlich wollen sollte. Daher hatte ich (vielleicht ungeschickterweise) so absolut formuliert. In dem was Du da untersuchst, steckt für mich ein gefühltes Sicherheitsrisiko, das ich noch nicht wirklich besser begründen kann... 😕

        Liebe Grüße,

        Felix Riesterer.

        1. problematische Seite

          Hallo Felix,

          Ich schrieb mit voller Absicht dazu, dass es mir um den Lern-Effekt ging.

          mir ging es um die Frage, ob man das tatsächlich wollen sollte. Daher hatte ich (vielleicht ungeschickterweise) so absolut formuliert. In dem was Du da untersuchst, steckt für mich ein gefühltes Sicherheitsrisiko, das ich noch nicht wirklich besser begründen kann... 😕

          Deshalb wollte ich ja nicht alle Event-Handler zulassen, sondern nur diesen einen mit dieser Prüfsumme 😉 von mir aus auch diesen einen mit dieser spezifischen nonce. Aber die Browser sind einfach noch nicht soweit.

          Warum Event-Handler? Um einen HTTP-Request zu sparen. Es geht mir nur um das nicht-blockierende Laden der Font-Datei, das nämlich nicht so richtig machbar ist von außerhalb. Klar kann ich in einem externen JS-Script einen load-Eventhandler auf das Link-Element setzen, aber wenn die Datei aus dem Cache kommt, dann gibt es da eine race condition: das load-Event ist ggfls schon vorbei, wenn ich es registrieren kann. Zur Zeit setze ich dann halt das Attribut bei DOMContentLoaded - schön ist aber anders, so wird der Zweck nicht so richtig erreicht. Ich bin mir allerdings auch noch nicht so recht im klaren darüber, wie man es sinnvoller machen kann.

          LG,
          CK