Some physicists 28 years ago needed a way to easily share experimental data and thus the web was born. This was generally considered to be a good move. Unfortunately, everything physicists touch ― from trigonometry to the strong nuclear force ― eventually becomes weaponized and so too has the Hypertext Transfer Protocol.
What can be attacked must be defended, and since tradition requires all security features to be a bolted-on afterthought, things… got a little complicated.
This article explains what secure headers are and how to implement these headers in Rails, Django, Express.js, Go, Nginx, and Apache.
Please note that some headers may be best configured in on your HTTP servers, while others should be set on the application layer. Use your own discretion here. You can test how well you’re doing with Mozilla’sObservatory.
Did we get anything wrong? Contact us at [emailprotected] . HTTP Security Headers Content Security Policy HTTP Strict Transport Security (HSTS) HTTP Public Key Pinning (HPKP) X-Content-Type-Options X-XSS-Protection X-XSS-Protection: 0; X-XSS-Protection: 1; X-XSS-Protection: 1; mode=block Why?Cross Site Scripting, commonly abbreviated XSS, is an attack where the attacker causes a page to load some malicious javascript. X-XSS-Protection is a feature in Chrome and Internet Explorer that is designed to protect against “reflected” XSS attacks ― where an attacker is sending the malicious payload as part of the request.
X-XSS-Protection: 0 turns it off.
X-XSS-Protection: 1 will filter out scripts that came from the request - but will still render the page
X-XSS-Protection: 1; mode=block when triggered, will block the whole page from being rendered.
Should I use it?Yes. Set X-XSS-Protection: 1; mode=block . The “filter bad scripts” mechanism is problematic; see here for why.
How? Platform What do I do? Rails 4 and 5 On by default Django SECURE_BROWSER_XSS_FILTER = True Express.js Use helmet Go Use unrolled/secure Nginx add_header X-XSS-Protection "1; mode=block"; Apache Header always set X-XSS-Protection "1; mode=block" I want to know moreX-XSS-Protection - MDN
Content Security Policy Content-Security-Policy: <policy> Why?Content Security Policy can be thought of as much more advanced version of the X-XSS-Protection header above. While X-XSS-Protection will block scripts that come from the request, it’s not going to stop an XSS attack that involves storing a malicious script on your server or loading an external resource with a malicious script in it.
CSP gives you a language to define where the browser can load resources from. You can white list origins for scripts, images, fonts, stylesheets, etc in a very granular manner. You can also compare any loaded content against a hash or signature.
Should I use it?Yes. It won’t prevent all XSS attacks, but it’s a significant mitigation against their impact, and an important aspect of defense-in-depth. That said, it can be hard to implement. If you’re an intrepid reader and went ahead and checked the headersappcanary.com returns, you’ll see that we don’t have CSP implemented yet. There are some rails development plugins we’re using that are holding us back from a CSP implementation that will have an actually security impact. We’re working on it, and will write about it in the next instalment!
How?Writing a CSP policy can be challenging. See here for a list of all the directives you can employ. A good place to start is here .
Platform What do I do? Rails 4 and 5 Use secureheaders Django Use django-csp Express.js Use helmet/csp Go Use unrolled/secure Nginx add_header Content-Security-Policy "<policy>"; Apache Header always set Content-Security-Policy "<policy>" I want to know more Content-Security-Policy - MDN CSP Quick Reference Guide Google’s CSP Guide HTTP Strict Transport Security (HSTS) Strict-Transport-Security: max-age=<expire-time> Strict-Transport-Security: max-age=<expire-time>; includeSubDomains Strict-Transport-Security: max-age=<expire-time>; preload Why?When we want to securely communicate with someone, we face two problems. The first problem is privacy; we want to make sure the messages we send can only be read by the recipient, and no one else. The other problem is that of authentication: how do we know the recipient is who they say they are?
HTTPS solves the first problem with encryption, though it has some major issues with authentication (more on this later, see). The HSTS header solves the meta-problem: how do you know if the person you’re talking to actually supports encryption?
HSTS mitigates an attack called sslstrip . Suppose you’re using a hostile network, where a malicious attacker controls the wifi router. The attacker can disable encryption between you and the websites you’re browsin