In the last couple of months, I’ve tried to improve the overall security of this site. I’ve started by putting my server behind Cloudflare to get HTTPS (along with other nice availability/performance improvements). Then I closed my eyes and enabled HSTS. I even dared adding this site to the HSTS preload list (i.e., the list of HSTS-enabled websites loaded in all modern browsers). Today I’m taking this a step further with the addition of some security-related HTTP headers. You might say that this was the very first thing I should’ve done and you’d be right to say so, but here comes :) From now on, if you take a look at the initial response, you’ll see that the following headers (among others) are being sent to you:
... X-Frame-Options "SAMEORIGIN" X-Xss-Protection "1; mode=block" X-Content-Type-Options "nosniff" content-security-policy: "default-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src * data:; script-src 'self' 'unsafe-inline' https://ajax.googleapis.com https://apis.google.com https://*.linkedin.com https://platform.twitter.com https://connect.facebook.net;child-src 'self' https://accounts.google.com https://apis.google.com https://platform.twitter.com https://*.facebook.com; font-src 'self' https://fonts.gstatic.com data:; frame-ancestors 'none';report-uri https://www.dsebastien.net/csp_report.php; connect-src 'self'; form-action 'self'; upgrade-insecure-requests; reflected-xss block; base-uri https://www.dsebastien.net; object-src 'none'"
The X-* headers give additional protection against clickjacking, cross-site scripting (XSS) and preventing some user agents from doing mime type sniffing. Those are nice, but the main one is the Content Security Policy (CSP). There are tons of articles about what a CSP is and how to configure one so I won’t go into the details of that. Any security expert will quickly notice that this isn’t the strictest CSP (far from it) because it allows ‘unsafe-inline’ for scripts & styles. The thing is that adding hashes or nonces to all scripts and styles is not an easy thing to do; even less so when you inherit that from many wordpress plugins… Also, some minified code (e.g., jQuery plugins) uses eval (evil?). For now, I’ve decided to lower my security goal. I’ll surely revisit this later though (probably with the new version of the site). Notice that the CSP makes some older HTTP headers redundant (e.g., X-Frame-Options) but I’m still keeping the older variants just for the sake of wider support. These will go away over time. Here are some tips if you want to go about and create a CSP for your site/domain:
- start with the report-only mode. It’ll only log errors in the console and will not actually block anything; this is a great starting point:
content-security-policy-report-only: default-src 'none';
- use tools such as the CSP extension for Fiddler or an online CSP generator
- once you’ve got rid of all console errors, remove ‘report-only’ to make your CSP effective
- configure a ‘report-uri’ to be aware of CSP-related issues. Just be careful with this as attackers might probably take advantage of that (i.e., do not mail yourself all violations :p)
More generally, you can use online tools such as this one to review your site’s security headers. If you look at my site there, you’ll see that I could add HTTP Public Key Pinning (HPKP) headers to improve security a bit more. I won’t do it though as I don’t want my site to break whenever CloudFlare decides to present a new certificate in front of my site…
As a side note, if you’re using Apache, you can configure security headers through .htaccess files and the headers module (mod_headers). Here’s an example:
Header always set X-Frame-Options "SAMEORIGIN" ...
I’m sure that this site still has many vulnerabilities, but there aren’t enough hours in the day for me to fix everything at once. I have other improvements in mind, but that’ll be for later! :)