This week, tCell sponsored BSidesSF. Many things I’ve heard about the conference proved to be true, and the technical depth of conversations I had at our table was definitely enough to keep me on my toes. One of the most interesting conversations was with a company that wanted to talk about Content Security Policies (CSP). They had come to the conclusion that new revisions of the PCI security standards would require that they implement CSP and work much harder to control inline scripts on their application suite.
CSP Nonces, Scripts and Controlling Script Execution, oh my!
CSPs are an important component of defending against XSS attacks because they prevent a user’s browser from loading content from someplace they shouldn’t. (I’ve previously written about using CSP as a method of defending against unauthorized insertion of Coinhive into a web page you control.)
The discussion I had with these security engineers centered around CSP nonces, specifically, on how the CSP specification provides a much-less commonly used method to control inline scripts called the script nonce. (Here’s a good tutorial from Google.) Script nonces are conceptually simple: the application tags each script with a one-time use number called a nonce, and the CSP header that comes along with the page lists all of the allowed nonces for the page. Before the browser runs a script, it checks that the nonce in the CSP header and the nonce on the page match.
Script nonces are hard to use in large-scale applications because different chunks of code, perhaps even running on different machines, can generate scripts and CSP headers, and if you can’t link the two together for each page load, user experience will be negatively affected.
Not surprisingly, very few major sites use script nonces. As usual, when you want to dig in to the details of how websites are served up, we’ll use Scott Helme’s excellent securityheaders.com. For any web site, we can print out the complete set of headers. Twitter is one of the few major sites that uses CSP nonces, which you can see by looking for the word “nonce” in HTTP headers Twitter is serving up. You can also make sure that the nonce changes on each load by refreshing the page and seeing the nonce value change.
My investigation of a few major sites showed that script nonces are not at all common (only Twitter uses them), and even CSP was a minority of big sites (only Twitter, Facebook, and YouTube even use CSP at all). If you’re having trouble implementing CSP, you’re not alone. You’re in the company of Google, Netflix, Reddit, Wikipedia, and Amazon. Need to start controlling scripts better? Give us a call!