Re: Updated script hash proposal (non spec text)

This proposal (and the now-implemented proposal to extend the allowed 
characters in nonce-source to encompass base64 [0]) need clarification 
on handling '=', commonly used for padding base64. This character is not 
required for decoding, but is commonly added by base64 encoders.

I am concerned that users will use techniques like the ones described in 
this proposal under "Computing hash values" and Script-hash unobtrusive 
workflow", both of which cause "=" to be appended, and will incorrectly 
have their hashes rejected if "=" isn't considered a valid character 
(which is the case for the current different of nonce-source, for example).

I believe this could also be a concern for users of nonce-source, who I 
imagine will probably use a technique similar to:

head -c 16 /dev/urandom | base64

to generate their nonces, which will also have '=' appended for padding.

There are two options here: we can either tell implementers to strip the 
unnecessary ='s from their nonces and hashes, or include them in the 
definition of valid nonce-/hash-sources. I prefer the second option for 
simplicity.

A patch to update the ABNF definitions in the spec is attached.

[0] http://lists.w3.org/Archives/Public/public-webappsec/2013Jun/0123.html

On 09/19/2013 03:46 PM, Neil Matatall wrote:
> Sorry for the long period of silence, I've been doing some evangelizing.
>
> Script hashes will be another source expression. Per script hash, the
> algorithm and digest length precede the actual hash value. e.g.:
>
> script-src 'sha256-0byNO6Svx+EJYSy3Osvd2sBSyTAlqh+ClC7au33rgqE'
>
> If a script hash source is specified and the user agent understands
> it, the browser should ignore the 'unsafe-inline' directive for
> backwards compatibility. Any inline script whose computed hash value
> does not match a hash specified in the hash sources should not be
> executed and an informative error message should be displayed
> including the expected hash value.
>
> If multiple hashing algorithms are specified in the CSP header, the
> browser must compute all possible hashes for each inline script block.
> If the computed hash matches any computed hash in the header with a
> matching algorithm+digest length, the script should execute. There was
> talk of limiting this to one algorithm per header, but CDNs complicate
> things.
>
> This is not meant to and should not support dynamic javascript. Hashes
> should not be computed dynamically (at least not in production).
>
> === Computing hash values
>
> base64encode(<hashing algorithm>(UTF-8(<content of script tag>)))
>
> <script>
>    alert(1);
> </script>
>
> base64encode(sha256(UTF-8("\n  alert(1);\n")))
>
> === Script-hash unobtrusive workflow (PoC)
>
> Unfortunately, many online hashing services will strip
> leading/trailing whitespace which is not what we want.
>
> I wrote a quick and dirty method for computing all script-hashes on a page:
>
> $.each($('script'), function(index, x) {
>    console.log(CryptoJS.SHA256(x.innerHTML).toString(CryptoJS.enc.Base64));
> });
>
> Here's the equivilent openssl command:
>
> openssl dgst -sha256 -binary | base64
>
> I wrote a more thorough rails plugin and explained how it works in [1]
> including a (low quality) video on how the developer workflow would
> work: [2].
>
> Essentially:
> 1) Find all inline scripts - search through the source code of any
> file that could be rendered / displayed to a user.
> 2) Extract the content of each inline script, hash according to the algo above.
> 3) Store as Filename -> [hashes] mapping. In a configuration file, for example.
> 4) Any time a file is rendered, the corresponding hashes are added to
> the CSP header.
>
> I believe this can be built in to every framework and be unobtrusive.
>
> [1] http://nmatatal.blogspot.com/2013/09/how-my-script-hash-poc-works.html
> [2] http://www.youtube.com/watch?v=Bc2hvziTRxg
>
> p.s. I support both script nonce and script hash, I think we need to
> have both :-/
>

Received on Friday, 22 November 2013 23:53:32 UTC