W3C home > Mailing lists > Public > public-webappsec@w3.org > April 2016

Re: Making it easier to deploy CSP.

From: Mike West <mkwst@google.com>
Date: Mon, 11 Apr 2016 17:37:09 +0200
Message-ID: <CAKXHy=f+6v2XNT6=YQ2-NWak5cqOE3jtL+iCszb+e1iHugZZhA@mail.gmail.com>
To: "public-webappsec@w3.org" <public-webappsec@w3.org>
Cc: Lukas Weichselbaum <lwe@google.com>, Michele Spagnuolo <mikispag@google.com>, Artur Janc <aaj@google.com>, Devdatta Akhawe <dev.akhawe@gmail.com>, Martin Thomson <martin.thomson@gmail.com>, Tanvi Vyas <tanvi@mozilla.com>, Dan Veditz <dveditz@mozilla.com>, Christoph Kerschbaumer <ckerschbaumer@mozilla.com>, John Wilander <wilander@apple.com>, Rob Trace <Rob.Trace@microsoft.com>, Ted Dinklocker <Ted.Dinklocker@microsoft.com>, Crispin Cowan <crispin@microsoft.com>
Based on Artur, et al's experience deploying 'unsafe-dynamic' on Google
properties, I think it's a good model to experiment with.

>From reading through this thread again, my takeaway is that Dev is
skeptical about the backwards compatibility story, and believes we might be
at the point where there are diminishing returns to extending the current
model, as opposed to breaking it entirely with a versioning scheme of some
sort. I'm not convinced we've hit that wall yet, but I agree with the
underlying assertion that CSP is getting (even more) complicated.

Whether or not CSP3 is the right time to introduce real syntax changes (
https://tools.ietf.org/html/draft-reschke-http-jfv-03, anyone?), this seems
like a pretty small complication to add for a pretty big benefit. I've
taken a first pass at defining the behavior we're interested in (
https://github.com/w3c/webappsec-csp/commit/6210614603184fa9d7e5ed02b34e08d9144c20fa),
and it's something I'd like to ship somewhat quickly in Chrome.

CCing some other browser vendor reps in the hopes that my interpretation is
shared. :)

-mike

On Sun, Mar 27, 2016 at 9:17 AM, Artur Janc <aaj@google.com> wrote:

> As a quick update, we are currently testing 'unsafe-dynamic' on a few
> user-facing sites, including https://bugs.chromium.org
>
> The relevant bits of the policy are:
> Content-Security-Policy: script-src 'unsafe-inline' 'nonce-..'
> https://www.gstatic.com/recaptcha/api2/ 'unsafe-dynamic'; object-src
> 'none';
>
> On bugs.chromium.org the main application change was to add the `nonce'
> attribute to trusted external scripts, e.g.
> <script src="https://www.google.com/recaptcha/api.js"
> nonce="..."></script>
>
> The ReCAPTCHA API loads additional external sub-scripts, and
> 'unsafe-dynamic' allows them to execute. This has two main benefits for the
> site:
> 1. It facilitates creating a policy for users of most JS APIs -- the site
> owner doesn't have to figure out the locations of all JS sub-resources
> loaded by each API, as long the top-level script is trusted and given a CSP
> nonce. It also reduces the potential for breakage if paths of sub-scripts
> ever change.
> 2. It makes for a stricter policy. With 'unsafe-dynamic', dangerous
> resources in whitelisted domains [1,2] are no longer a problem because
> trust is now based on the presence of a nonce and the whitelist is ignored.
>
> With a policy like the one above, browsers which support CSP, but don't
> support nonces will allow scripts to execute based on 'unsafe-inline' and
> the source whitelist. Browsers which support nonces but don't support
> unsafe-dynamic will ignore 'unsafe-inline' and will rely on the nonce and
> the whitelist. Browsers which support unsafe-dynamic will rely solely on
> the nonce and will transitively trust dynamically created scripts, and will
> additionally ignore the whitelist.
>
> Based on what we have seen so far this appears to be a fairly promising
> approach and we will experiment with it in larger applications in the near
> future.
>
> Cheers,
> -Artur
>
> [1]
> https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22
> [2]
> https://lcamtuf.blogspot.com/2011/08/subtle-deadly-problem-with-csp.html
>
> On Fri, Feb 12, 2016 at 2:56 PM, Mike West <mkwst@google.com> wrote:
>
>> Hello, lovely webappsecians!
>>
>> I've been talking to Google's security folks about their adventures in
>> deploying CSP to Google products. The TL;DR is that they're scared of
>> whitelists (because of all the legacy junk on `google.com` and `
>> googleapis.com`), and are frustrated with loading widgets and libraries
>> whose content they don't control. They love (cryptographic) nonces and
>> hashes, and have a small proposal for a new source expression which would
>> make deployment at Google (and hopefully elsewhere) easier.
>>
>> # Whitelists
>>
>> As it turns out, `google.com` and other origins we depend on are full of
>> terrible endpoints that allow user-injected script (see `
>> https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22`,
>> for example). We mitigate this risk with extensive `script-src` directives
>> full of deep paths, which is brittle, awkward, and sometimes impossible
>> (because some folks dynamically generate all the things!). It's also
>> vulnerable to open redirects stripping the path, and of course sprawling
>> origins like ours have open redirects too. Huzzah for legacy!
>>
>> The security team here would be thrilled if they could use
>> (cryptographic) nonces and hashes for everything instead of relying on
>> whitelists.
>>
>> But:
>>
>> # Dynamic Content
>>
>> Widgets and libraries make this dream difficult, as they insist on
>> loading code from various places, and don't do a good job explaining what
>> code they'll actually need before doing so (I'm looking at you, Google
>> Maps). We can certainly add all of these paths to the whitelists as well,
>> but they change on a somewhat regular basis, and end up with the same
>> drawbacks as noted above.
>>
>> As it turns out, in the presence of a (cryptographic) nonce, this is
>> something that the library itself could deal with, by grabbing the token
>> from somewhere on the page, and using it when injecting its own script. The
>> token is implicitly a script-execution capability:
>>
>> ```
>> var ce = document.createElement;
>> window.nonce =
>> document.querySelector('script[nonce]').getAttribute('nonce');
>> document.createElement = function (e) {
>>  var el = ce.apply(this, arguments);
>>  el.setAttribute('nonce', window.nonce);
>>  return el;
>> };
>> ```
>>
>> While we work on updating every library in the entire world to use this
>> pattern, we're also experimenting with getting the browser to do the
>> busywork for us, in a backwards compatible way:
>>
>> # 'unsafe-dynamic'
>>
>> We're proposing a new `'unsafe-dynamic'` source expression which has the
>> following effects when added to the `script-src` directive:
>>
>> 1.  If neither a hash nor a nonce is present in the directive's source
>> list, do nothing. Otherwise:
>>
>> 2.  Ignore all `scheme-source` and `host-source`source expressions, as
>> well as `'unsafe-inline'`. This gives us backwards compatibility, and
>> ensures that developers who opt-into this mechanism won't leave themselves
>> open to whitelist-based vulnerabilities; if you use 'unsafe-dynamic',
>> that's all you use. That is, given the policy: `script-src 'unsafe-inline'
>> https://example.com/ 'nonce-abcdef' 'unsafe-dynamic'`, Safari would see
>> `script-src 'unsafe-inline' https://example.com/` <https://example.com/>
>> (as it doesn't support nonces, while supporting browsers would see
>> `script-src 'nonce-abcdef' 'unsafe-dynamic'`.
>>
>> 3.  Skip CSP enforcement on script execution for `<script>` elements
>> which are not "parser-inserted". This basically boils down to automatically
>> applying the capability noted above for scripts inserted via something like
>> `appendChild(createElement('script'))`. We're only focusing on
>> non-parser-inserted scripts, as (anecdotally) `document.write` and
>> `innerHTML` are significantly more likely to contribute to XSS than
>> `appendChild`. Moreover, `appendChild` accounts for the large majority of
>> intentionally inserted scripts, based on an analysis of several dozen
>> popular origins.
>>
>> You can play with most of this in Chrome Canary (behind
>> chrome://flags/#enable-experimental-web-platform-features). Based on some
>> experimentation with a crazy nonce-injecting extension, a policy like
>> `'unsafe-eval' 'nonce-abcdef' 'unsafe-dynamic'` allows strict whitelisting
>> with very little breakage on various Google properties and a few other high
>> profile sites. The folks I've CC'd have more details on those tests for
>> y'all if you're interested.
>>
>> I'll write up a patch to CSP to spell this out in more detail, but I hope
>> the overview here is enough to get some early feedback. :)
>>
>> -mike
>>
>
>
Received on Monday, 11 April 2016 15:38:02 UTC

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