- From: Brian Smith <brian@briansmith.org>
- Date: Thu, 6 Nov 2014 17:02:59 -0800
- 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