One of the most common (and most annoying) web application vulnerabilities is XSS (Cross Site Scripting). Depending on the context it can either be an irritation or downright dangerous. To defend against this vulnerability you have a few options; proper input/output escaping (something that should be happening anyway but everyone makes mistakes) or place a Web Application Firewall in the way (does slow down the application). What if there was a better way? A control that didn't rely on developers being forgetful or add extra overhead to the user experience. As a matter of fact there is such a way: Content Security Policy
The Content Security Policy (CSP) is an effective web application security control to prevent XSS and other injection attacks. CSP enacts certain "policies" that are sent to the user's browser. These policies act as a whitelist for where certain resources are allowed to come from.
There are two ways to implement a Content Security Policy. The first (and preferred) method is to set it as a response header. The server will issue the CSP header with a "policy" as defined by the developer.
The second way to implement a CSP is to provide it as a "<meta>" tag in the html of the page. Please note that this is not the best way to implement the control, as the policy will not apply to "frame-ancestors", "report-uri", or "sandbox" directives.
In the situation where the CSP is defined as a response header and as a meta tag at the same time Chrome and Firefox will respect whichever policy is the most restrictive
When a CSP is defined as a response header it will take the following form
Content-Security-Policy: script-src 'self' https://maxcdn.bootstrapcdn.com
content-security-policy.com provides a list of all the key directives and source options which I will display below.
The following are some important directives that we should point out
It is important to note that by default all policy directives are left open. For example, if we don't specify a list of safe origins for images, an image can be loaded from any domain. The way we get around this is through the "default-src" directive. As mentioned in Google's Web Development Fundamentals "Generally, [default-src] applies to any directive that ends with "-src"". By setting this directive, we are telling the browser to only load a variety of resources from a single domain (so long as you specify it).
CSP is very effective at preventing injection attacks, but wouldn't you want to find and fix the underlying vulnerabilities/bugs? The "report-uri" directive can help in that regard. This directive will ask the browser to report any CSP violations it detects to a specific endpoint through POST requests. This can help you fix any misconfigurations that may exist in your web app.
There is a dangerous alternative to using hashes. Simply putting the 'unsafe-inline' source in the CSP will allow any inline scripts to run. This should be a last resort and not something implemented over the long term.
Another great feature of Content Security Policy is that you can ensure your developers are following a basic Application Security Principle: don't use 'eval'. When configured correctly CSP won't allow 'eval' or any similar dangerous functions to trigger. This behavior can be overwritten by the 'unsafe-eval' source.
As mentioned above, the reporting functionality is very beneficial for logging and alerting to issues. If you have a particularly complex app, it may be helpful to only implement the reporting and not actually restrict anything. That is where "Content-Security-Policy-Report-Only" comes in. This header wont block any resources but it will report all violations of the CSP.
This can be incredibly useful if you are planning to change your policies, as you can see ahead of time if anything will break.