W3C home > Mailing lists > Public > public-webappsec@w3.org > July 2013

Re: Proposal for script-hash directive in CSP 1.1

From: Neil Matatall <neilm@twitter.com>
Date: Tue, 2 Jul 2013 15:19:18 -0700
Message-ID: <CAOFLtbh_TJLdDuJh4nEfGx7f8EfKfnnf5_XDNem=+MPBZo=yZw@mail.gmail.com>
To: Brad Hill <hillbrad@gmail.com>
Cc: Nicholas Green <ngreen@twitter.com>, "public-webappsec@w3.org" <public-webappsec@w3.org>
>    - should attributes of the script tag be included?  (e.g. whether it is javascript, vbscript, ruby or json?)

Not exactly on topic, but specifically in the case of
type="application/json", we're already relying on this to be
non-executable. Is this a bad assumption to take? We're banking on
this pretty heavily.

Removing Inline Javascript (for CSP):
http://nmatatal.blogspot.com/2013/01/removing-inline-javascript-for-csp.html
"""
Loading complex objects: place the object in the content of script tag
as HTML-escaped JSON, read the innerHTML of the span, and parse it as
JSON.

This technique is also outlined in the OWASP XSS Prevention Cheat
Sheet Thanks to @rx: improved on this a bit by using a script tag
rather than a span. The values must still be escaped! Use html entity
encoding here too. If you must, json encoding will work as well.
Otherwise, breaking out of the script tag which is parsed by the
browser BEFORE the javascript is parsed/executed. Again, even invalid
JSON is trumped by what the browser thinks you meant to do and it will
happily render an attackers closing script tag and what is to follow.

<script type="application/json" id="init_data">
  <%= h(@donkey.to_json)%>
</script>

Note! You MUST set type="application/json" or CSP will consider it
code, and block the inline script.
In an external JS file, read the value as raw html and parse the
encapsulated JSON to yield an associative array (a.k.a. map,
dictionary, hash, etc).
"""

On Tue, Jul 2, 2013 at 3:08 PM, Brad Hill <hillbrad@gmail.com> wrote:
> A good start, but needs a lot more work. My todo list from mid-last month on
> this (that might have gotten eaten by DMARC mail policy at my PayPal
> account)  was:
>
>  Rather than have a script-hash directive, I would suggest using the RFC
> 6920 syntax (http://tools.ietf.org/html/rfc6920) as a source expression is a
> good fit with the current pattern of using nonces as such.
>
>  Specify which hash algorithms CSP 1.1 would require support for.
>
>  Specify whether and to what extent truncation is allowed.
>
>  Specify what to do with the content-type attribute of ni: URIs if we allow
> this to be used for non-inline content... or should this be used to
> determine the type (css, js, vbs, etc..) of the inline resource?
>
>  Specify an algorithm to exactly determine the bytes-to-be-hashed in a
> reliable and cross-browser manner.  I would suggest that this should be
> defined in terms of the HTML5 parsing algorithm, with some restrictions such
> as requiring any resource employing hash sources declare an explicit
> encoding. (but not just utf8)
>
>  *shudder* Is canonicalization necessary?  I hope not.
>
>  Think about and determine what needs to be covered by the
> bytes-to-be-hashed:
>
>    - should attributes of the script tag be included?  (e.g. whether it is
> javascript, vbscript, ruby or json?)
>
>  Specify algorithm agility behavior
>
>    - what to do if a policy specifies only SHA4 hashes and a user agent
> doesn't understand SHA4?  fail?  fallback to unsafe-inline?
>
>    - possibly: if a policy specifies SHA1 and SHA3 hashes of the same
> content what should user agent behavior be?  allow all as valid?  only trust
> the strongest hashes it understands how to process in a given policy string?
> In the composite policy?
>
>
>
> -Brad
>
>
>
> On Tue, Jul 2, 2013 at 2:57 PM, Neil Matatall <neilm@twitter.com> wrote:
>>
>> Per the conversation in today's call where we were looking for a
>> script-hash spec proposal. Were there objections to this? Good
>> starting point?
>>
>> On Wed, Feb 13, 2013 at 2:12 PM, Nicholas Green <ngreen@twitter.com>
>> wrote:
>> > In English:
>> >
>> > The contents of every script tag will be encoded to utf-8 then hashed,
>> > including all leading and trailing whitespace.  We hash the contents
>> > of each script tag with the hashing algorithm specified in the
>> > script-hash directive.  If the calculated hash's base64 encoding
>> > matches the base64 encoding of a hash value listed in the CSP header,
>> > we execute the script.  Otherwise we block & report.
>> >
>> > In spec:
>> >
>> > The script-hash directive restricts script execution by requiring that
>> > the hash of a script's contents must appear in the directive in order
>> > for the script to be executed.  The syntax for the name and value of
>> > the directive are described by the following ABNF grammar:
>> >
>> > directive-name      = "script-hash"
>> > directive-value     = hash-algorithm ":" hash-list
>> > hash-list           = *WSP [ hash-value *( 1*WSP hash-value ) *WSP ]
>> > hash-value          = 1*hash-char *( 1*hash-char )
>> > hash-char           = ALPHA / DIGIT / "+" / "/" / "="
>> > hash-algorithm      = "sha1" / "sha256"
>> >
>> > If script-hash is NOT specified as a directive:
>> >
>> > * The user agent MUST follow script-src behavior or inherited
>> > default-src behavior for inline scripts.
>> >
>> > If script-hash IS specified as a directive
>> >
>> > * Whenever the user agent would execute an inline script from a script
>> > element, the user agent MUST NOT execute the script unless the base64
>> > (rfc4648) encoding of the digest of the utf-8 encoded script contents
>> > when hashed with the hash-algorithm specified in the script-hash
>> > directive matches a base64 hash-value in the list of hash-values.
>> > User agents should pad the hash-values with '=' as necessary to make
>> > them valid base64 strings.
>> > * Whenever the user agent would execute a script from an inline event
>> > handler, instead the user agent MUST NOT execute the script.
>> > * Whenever the user agent would execute script contained in a
>> > javascript URI, instead the user agent MUST NOT execute the script.
>> > * The content-type HTTP header SHOULD be set.
>> >
>> >
>>
>
Received on Tuesday, 2 July 2013 22:19:46 UTC

This archive was generated by hypermail 2.3.1 : Monday, 23 October 2017 14:54:02 UTC