This is the third article in the series of hardening this webserver. If you have not read them, please read: Protecting my Webserver and SSL Cypher hardening. In this article, I show the usage of the Content-Security-Policy header. This header helps you reduce XSS risks on modern browsers by declaring what dynamic resources are allowed to load via an HTTP Header.
Why use the CSP header
Ok, we have this header but what will it do for my site. Well, the main reason is that you can prevent Cross Site Scripting (XSS). Which is a scam that still is very likely according to the WhiteHat security there is still an almost 50% chance that your site has an XSS vulnerability and holds the 3rd place, The numbers 1 and 2 are covered in the previous posts.
A short history
The header is introduced in 2012/2013 and took some time for all browser to support and act on it. The image below depicts the support for the header on the Netherlands:
As you can see there is support of about 90% worldwide. More reason to use it.
What does it do
The introduction already gave an answer to that it is a statement on what dynamic resources are loaded by the website. For example, you will only allow scripts that you host yourself are loaded into the page.
Implementing the Header
The implementation of the header can be cumbersome if your site uses a lot of resources that are loaded different CDN's.
For example, if you only use resources from your own domain the header is very simple:
Header set Content-Security-Policy "default-src 'self';"
If your site attempts to load a resource from somewhere else the user will not receive that resource and
you get a message like this one in the Chrome Developer Tools:
Refused to load the script 'script-uri' because it violates the following Content Security Policy directive: "your CSP directive".
Quite a few site's have external code embedded, think of Google statistics, Google Adds and like I have Disqus.
That imposes a bit more tinkering in for the header to be correct.
The full specification can be found at the Web Consortium. This is along read and not always that clear. If you start experimenting with this header first take a look at (somewhat outdated) https://content-security-policy.com/. This site provides a condensed version of the specification and will allow you to get started quickly.
For this site for example I use the following values for the header:
Content-Security-Policy:default-src 'self'; script-src 'unsafe-inline' 'unsafe-eval' 'self' https:; style-src 'self' 'unsafe-inline' https:; font-src 'self' data: fonts.gstatic.com; img-src 'self' https:; frame-src 'self' disqus.com; connect-src 'self' https:;
If you look closely at this header a few things should standout for you; there are multiple
unsafe-* elements in it. That is something I still need to work upon. I do use some inline scripting that I should remove.
Implement CORS for all resources that are loaded cross domain.