Content Security Policy is turning out to be one of the solutions at "scale" for fixing cross site scripting. In this blog I have tried condensing data from multiple sources from the internet to focus on the important things one need to know to implement CSP for the first time. The idea of this blog post is to help security engineers who want to figure out where to start on CSP if they are in the process of implementing one on their production environments.
Introducing Content Security Policy:
Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement or distribution of malware.
The web’s security model is rooted in the same origin policy, code from https://mybank.com should only have access to https://mybank.com’s data, and https://evil.example.com should certainly never be allowed access. Each origin is kept isolated from the rest of the web, giving developers a safe sandbox in which to build and play. In theory, this is perfectly brilliant. In practice, attackers have found clever ways to subvert the system
CSP is designed to be fully backward compatible; browsers that don't support it still work with servers that implement it, and vice-versa. Browsers that don't support CSP simply ignore it, functioning as usual, defaulting to the standard same-origin policy for web content. If the site doesn't offer the CSP header, browsers likewise use the standard same-origin policy
Here is the list of browsers that support CSP.
Pre-Requisites:
Before jumping on to the implementation part, It is recommended you go through the W3C CSP recommendations and also few other links I think can be helpful for easy implementation:
Pre-production Testing:
- Before implementing CSP on the production server, I recommended to use CSP tester chrome plugin to test the effects and to identify correct directives to be used as per your need.
- This plugin simulates the behaviour of an actual CSP header sent in the response.
- CSP tester plugin + Console Errors are the best way one can debug the error messages which occur by adding CSP header.
Secure way of Implementing CSP:
- There are multiple ways to implement CSP. Just by whitelisting javascript source files, one does not end up securing the application from XSS. Developers normally implement CSP in a way which makes their work easier leaving the application still vulnerable to XSS.
CSP Directives:
Content-Security-Policy: default-src 'none’
|
The first step to start a CSP header is to specify which is the default source list. A better practise to implement this is to call it ‘none’, which will encourage us to whitelist all the sources we have.
Few sources to be considered [script,style,connect,object,img,child]
Content-Security-Policy: script-src 'self' https://img1a.flixcart.com; https://img1a.flixcart.com
|
Whitelist all the script origins as shown in above example and make sure we do not add ‘unsafe-inline’ to the script-src directive. If we allow inline javascript to run than it could defeat the purpose of CSP.
With unsafe-inline we allow inline JS to execute in our application, which means if the application is vulnerable to XSS, an attacker will still be able to execute JS in the context of our application.
Handling Inline JS:
If we have inline javascript which requires to execute then we need to specify a random nonce in the header. We have to generate this nonce at the server end and send it across in the CSP header and consume the same in our inline Javascripts.
To use a nonce, give your script tag a nonce attribute. Its value must match one in the list of trusted sources.
Example:
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa
|
<script nonce=EDNnf03nceIOfn39fn3e9h3sdfa>
//Some inline code I cant remove yet, but need to asap. </script> |
Example Policy:
Content-Security-Policy:
default-src 'none'; script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa http://img1a.flixcart.com http://img2a.flixcart.com https://www.google-analytics.com https://s3.amazonaws.com;
style-src https://img1a.flixcart.com ‘unsafe-inline’ ‘unsafe-eval’; img-src https://img1a.flixcart.com;
connect-src https://api.mybank.com; child-src 'self'; font-src 'self' *
report-uri https://www.flipkart.com/appErrors
|
Here is the explanation of the above policy:
default-src - We default all origins as none, which forces us to specify all the source origins in all the ‘src’ directives.
script-src - We mention all the script sources we want to consume our JS files from, also all the analytics files and if any inline nonces.
style-src - All the CSS files needs to go in this directive.
img-src - All the image cdn sources need to be mentioned in this directive.
connect-src- All the Ajax(xhr) requests connections needs to be specified in this directive.
report-uri- This directive is important for debugging any violations which occur on production. A json blob is sent to the mentioned endpoint with appropriate error information.
For more clarity on CSP directives we suggest to follow this article.
Firefox recently came up with a feature that allows us to test the secure implementation of CSP on any website. Just by opening the developer console and typing in "security csp" one can see the entire report.
Firefox recently came up with a feature that allows us to test the secure implementation of CSP on any website. Just by opening the developer console and typing in "security csp" one can see the entire report.