- From: Mike West <mkwst@google.com>
- Date: Fri, 12 Feb 2016 14:56:58 +0100
- To: "public-webappsec@w3.org" <public-webappsec@w3.org>
- Cc: Artur Janc <aaj@google.com>, Lukas Weichselbaum <lwe@google.com>, Michele Spagnuolo <mikispag@google.com>
- Message-ID: <CAKXHy=d2Ggr-P_Om=L+vDMoze=_+QjdPExQ5T7XKBb1CuguGfw@mail.gmail.com>
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/` (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 Friday, 12 February 2016 13:57:55 UTC