W3C home > Mailing lists > Public > public-webappsec@w3.org > November 2014

Re: [CSP] Clarifications on nonces

From: Brian Smith <brian@briansmith.org>
Date: Thu, 6 Nov 2014 17:02:59 -0800
Message-ID: <CAFewVt4FdyOOTha9cuuLoaZWiEL7Ezod4Z04rOxqo1NJu=kFHw@mail.gmail.com>
To: Daniel Veditz <dveditz@mozilla.com>
Cc: "public-webappsec@w3.org" <public-webappsec@w3.org>
On Wed, Nov 5, 2014 at 8:24 PM, Daniel Veditz <dveditz@mozilla.com> wrote:
> On 11/5/2014 6:48 PM, Brian Smith wrote:
>> Case 1. Imagine that the web page contains a CSP nonce of X. Further,
>> assume that the page uses XHR to retrieve HTML fragments from a server,
>> and then inserts those fragments into the document. Further, assume that
>> an attacker learns the value X (because CSP doesn't require X to be
>> secret), and then inserts <script nonce=X> into that fragment retrieved
>> via XHR. It seems like the attacker's XSS will succeed, despite CSP.
>
> If the nonce is indeed used only once the only way the attacker will
> learn of it is if they are running script within the document, and if
> that is the case then they've already won.

I do not think this is true. Consider this counter-example:

First, imagine a web service violations.example.com/report, which
receives violation reports and then publishes them publicly. This is
allowed because CSP doesn't require CSP violations to be private.

Further assume that the attacker runs a service at
https://attacker.example.com/get-script that returns a <script> tag of
the attacker's choosing.

Now, consider this scenerio:

1. Our server generates a CSP with
report=uri=violations.example.com/report ; script-src 'nonce-12345'
2. Our server requests a script from https://attacker.example.com/get-script.
3. attacker.example.com returns a script without any nonce.
4. Our server transmits the headers (including our CSP) followed by
the attacker's script as the first chunk of a chunked HTTP response.
5. Our server sleeps for a while.
6. While the server is sleeping, the client receives the script tag
that it received from our server. It notices that the script doesn't
have a matching once, and so it refuses to execute the script. And,
because CSP requires it, it sends a violation report to
violations.example.com/report that contains the nonce.
7. Our server wakes up and asks attacker.example.com/get-script for
another script.
8. attacker.example.com asks violations.example.com for the last nonce
that was sent to it.
9. violations.example.com returns '12345'
10. attacker.example.com returns <script nonce=12345>...</script> to our server.
11. Our server transmits <script nonce-12345>...</script> to the
client as the second partial chunk of the document.
12. The client receives the attacker's <script
nonce=12345>...</script>, verifies that the nonce matches, and then
executes the attacker's script.

And, as I noted in my previous email in this thread, if you read the
CSP spec literally (which, I think, it how specs should be read), this
can actually be reduced to:

1. Our server generates a CSP with
report=uri=violations.example.com/report ; script-src 'nonce-12346'
2. Our server sends the CSP report and other headers to the client.
3. Our server requests a script from
https://attacker.example.com/get-script?nonce=12346, since it has
already satisfied the requirement that the nonce be kept secret until
the policy is transmitted.
3. attacker.example.com returns <script nonce=12346>...</script>
4. Our server transmits the the attacker's script to the client.
5. The client receives the attacker's <script
nonce=12346>...</script>, verifies that the nonce matches, and then
executes the attacker's script.

Now, obviously it is silly for our server to ask the attacker for
scripts to insert into the page. But, ultimately this is what all
(stored) XSS boils down to. It's even sillier to directly hand the
nonce to the attacker, but it wouldn't be surprising to have many ways
of *indirectly* giving the nonce to the attacker.

> Using nonce is weaker than not using it.; people should not design new
> sites around it. However if the alternative is for a legacy site to add
> 'unsafe-inline' then using a nonce is a lot safer.

I agree, and I think this is maybe the key design point of the CSP
hash and CSP nonce mechanisms: Maybe the goal isn't to create secure
ways of doing inline script and inline CSS, but rather the goal is
only to make them *less unsafe*. Perhaps this is something to note in
the security considerations for both mechanisms.

Still, I think it is worthwhile to have nonce (and hash) specified and
implemented in a safer way, such as by doing what Dev suggested.

Cheers,
Brian
Received on Friday, 7 November 2014 01:03:26 UTC

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