danten.io

Security Headers: Content Security Policy

Score an A+ in Your Security Report. Setup Your Content Security Policy.

[ Disclaimer: Well, actually it’s still an A. Learn more about the reasons below. ]

A few years back, I wrote up a post about HSTS: Improve Your Web Site Security Headers for better web site security and as a technical SEO tweak. It ended like this:

By using the above code in your .htaccess, you should reach grade A.

If you want to take it even further and go for that A+ you’ll need to also implement Content Security Policy (CSP) to prevent Cross-Site Scripting – XSS – attacks.

Applying CSP headers can be slightly more tricky than setting up HSTS, so it’s OK to save that task for a rainy day.

So the day to go for that A+ has come. It sure ain’t raining, but then who cares.

Let’s take a closer look at Content Security Policy. What’s this CSP thing all about?

Content Security Policy Introduction

Here’s what one of the more prominent sites about CSP - that is https://content-security-policy.com/ - tells us this about Content Security Policy:

Content-Security-Policy is the name of a HTTP response header that modern browsers use to enhance the security of the document (or web page). The Content-Security-Policy header allows you to restrict how resources such as JavaScript, CSS, or pretty much anything that the browser loads.

Although it is primarily used as a HTTP response header, you can also apply it via a meta tag.

Basically, CSP enforces the separation of code and data to allow only code from a white-list of sources to run in the page. This allows you to protect your site and your applications from malicious cross-site scripting (XSS) attacks that can be a significant security risk.

Basic CSP Examples

Using CSP you can control which content sources for JavaScript, CSS, Images etc. are permitted on your site. A very basic Content Security Policy might look like this:

Content-Security-Policy: default-src 'self'

The above would allow loading assets from your local origin only. You could use directive such as script-src, style-src, and img-src to define allowed sources for JS, CSS & images respectively.

So if you load let’s say images from your own site as well as from a trusted 3rd party domain, your CSP might look something like this:

Content-Security-Policy: img-src 'self' img.3rdpartydomain.com;

Note: Above is merely the basic CSP structure itself, once we add it to our Apache VirtualHost we’ll need to adjust the syntax accordingly.

You’ll find many examples over at https://content-security-policy.com/ for loading fonts, CSS style, scripts, audio/video, iframes etc. Mostly you’ll want to restrict sources to your ‘self’ as well as to trusted 3rd party sites, such as your CDN, your analytics or font source etc.

Adding CSP to Your Apache VirtualHost Configuration

Now, in my previous post I showed you how to get grade A, and by adding the security headers to your .htaccess. No more. This time we’ll simply add the Headers to the Apache <VirtualHost> configuration of the host you want to cover.

In my case - and since I’m refraining from JavaScript, external sources, CDNs etc. - I’d edit /etc/apache2/sites-enabled/danten.io-ssl.conf and add something like this:

1
2
3
4
5
6
7
<IfModule mod_headers.c>
  Header always set X-XSS-Protection "1; mode=block"
  Header always set Referrer-Policy "no-referrer-when-downgrade"
  Header always set Strict-Transport-Security "max-age=15552000;"
  Header always set Permissions-Policy "fullscreen=*,"
  Header always set Content-Security-Policy "style-src 'self' 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa88';"
</IfModule>

An Apache reload is needed:

$ /etc/init.d/apache2 reload (old-school) or $ systemctl reload apache2 (systemd way)

CSP: Inline Styles & Nonces

This allows CSS (style) only from ‘self’ aka my site. But now, what’s this ‘nonce’ thing?

Well, these CSP directives don’t cover inline scripts or CSS, and you’d usually want to avoid inline styles on your commercial site, and instead use an external CSS stylesheet file that is referenced in the header of the document. Inline CSS are not an elegant way of managing your styles, especially when you’ve got complex styles, they include pseudo-classes etc.

You could use the unsafe-inline for style or script directives, but hey the name’s already giving it away so to say: It just ain’t safe and does kinda nullify the entire point of deploying a CSP.

So what do you do? Exactly, you’d use a “nonce” - a “number only used once”. Or you could use a CSP hash, which is a similar concept.

Two steps are needed for nonces: You’d set the nonce in your CSP, then include the same nonce within your inline style so it’d look something like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<style nonce="EDNnf03nceIOfn39fn3e9h3sdfa88">
  body {
    font-family: Verdana, sans-serif;
    margin: auto;
    padding: 20px;
    max-width: 720px;
    text-align: left;
    background-color: #fff;
    word-wrap: break-word;
    overflow-wrap: break-word;
    line-height: 1.5;
    color: #444;
  }
...
</style>

The result of the above CSP in my Apache VirtualHost gives me a green A+ over at securityheaders.com . Note that you’ll find several web based tools out there that scan and analyse your web site’s security headers, so feel free to go pick the one you deem best.

So far so good. However…

Because I’m using Hugo as a statical site generator - a really very cool tool to build statical sites - and I’m using Hugo’s internal syntax highlighting as opposed to JavaScript based highlighter, I run into the issue that it’s currently not possible to change the actual returns of the highlighting style.

To work around this, I followed the instructions over at Hugo Syntax Highlighting avoiding Unsafe Inline , and simply generated a separate CSS file:

$ hugo gen chromastyles --style=dracula > syntax.css

I then included this is my site’s header, it works and voilà I’m good to go:

Back at the green A+ over at securityheaders.com.

Drawback:

Because of the CSS file and the additional round-trip my site’s Google PageSpeed score then drops to 99/100. Which is still “more than good” of course. But so is a green A when it comes to security headers. So how to balance this?

Actually, and for a basic and reasonably secure site such as mine - with no scripts/stylesheet - the additional security gain by deploying CSP is IMHO not very high.

So yeah, I’m opting for the 100/100 PageSpeed while holding onto my slogan:

No JavaScript. No Cookies. No CSS Stylesheets.

By now it’s actually raining outside, and it’s time for my favorite Saturday night activity these days. It involves positioning myself in a comfortable position and… Yeah you guessed it, sipping that tea while starting out with a new book. I might tell you more about that soon.

You might want to check out this excellent resource on the topic of Content Security Policy to learn more. CSP is powerful way of securing your site against XSS attacks, and for complex commercial sites running scripts and styles from various sources a solid CSP helps protect your user session data and keep out them bad guys.

:wq

#Apache #CSP #Security