New Rails security HTTP headers

Rails sends a couple of new security HTTP headers by default so you should probably know what they do. There are also a few additional ones, but they require a bit more configuration and thought.

The default headers

X-Frame-Options 'SAMEORIGIN' is sent by default. It means another website can only include this website in an iframe if it’s from the same origin. Allowed values are SAMEORIGIN, DENY and ALLOW-FROM https://example.com/ which allows you to include this site in an iframe on https://example.com/. This is a countermeasure against clickjacking, where an attacker includes a site in an iframe and uses CSS to make the contents transparent. If a user is logged into the site in the iframe, the attacker can position unsuspicious elements right behind links in the iframe. But because the links are transparent, the user won’t notice when she unintentionally clicks a link in the iframe. Here is a great write-up of the vulnerability.

Rails sends X-XSS-Protection 1; mode=block by default. This turns on the reflective XSS protection in Chrome, Internet Explorer and Safari. Reflective XSS is a string containing HTML/JavaScript that the user entered on one page and is repeated on the next page, for example after submitting a form. Allowed values are 0 (off), 1 (on) or 1; mode=block which will block the response rather than sanitizing or escaping the reflective XSS.

X-Content-Type-Options nosniff is also sent by default. This will tell the browser not to look for HTML in server responses and assume an HTML mime type if the content type is somehow ambiguous. This is the only allowed value.

Additional headers

Twitter published a gem to add also the following security-related headers.

The Content-Security-Policy header defines whitelist rules for Content Security Policy (CSP). Primarily, CSP is a set of rules to tell the browser from what source scripts may be executed and thus all other sources are disallowed. That means you can reduce the number of Cross-Site Scripting (XSS) vectors by, for example, allowing only scripts from your domain or disallowing inline scripts.
The support rate totals about 70% of all browsers currently in use. And it’s backward compatible, so the site will be fully functional in older browsers but won’t have the extra protection. Internet Explorer still only supports that header in versions 10+. Unfortunately the ability to whitelist source domains doesn’t seem to be supported by IE yet.
Because configuring these rules isn’t straightforward in larger projects, a strategy could be to first use the Content-Security-Policy-Report-Only header instead. It tells the browser to only report the policy violations to a URL endpoint or the browser’s console.
Here’s a more detailed introduction to CSP and a cheat sheet.

HTTP Strict Transport Security (HSTS) ensures the browser never visits the HTTP version of a website. The HTTP header looks like this: Strict-Transport-Security: max-age=31536000. The max-age parameter can be any value from 0 upwards, which is the number of seconds before the browser should re-read that header. Until then the browser will only visit the HTTPS version of the website, even if the user tries to go to the HTTP version. This mitigates man-in-the-middle attacks where TLS can be stripped out. See here for more details on HSTS.

The X-Download-Options HTTP header has only one option: X-Download-Options: noopen. This is for Internet Explorer from version 8 on to instruct the browser not to open a download directly in the browser, but instead to provide only the ‘Save’ option. The user has to first save it and then open it in an application. The reason for this is that when HTML files download from the application, the browser will render it directly inline. That means that the file renders as part of the application and has direct access to the security context of it, meaning it may run phishing attacks or maybe access critical domain cookies.

The X-Permitted-Cross-Domain-Policies HTTP header restricts Adobe Flash player’s access to data. The Adobe products PDF and Flash use a same-origin concept that sometimes allow cross-domain access. Flash on a.com will be able to access data on b.com if there is a Cross Domain Policy File at b.com/crossdomain.xml that allows data to be accessed from a.com (or from all sources).
Let’s assume you don’t use Flash and don’t want anybody to include content from your site on another domain. If so, do not create a crossdomain.xml file but send the following HTTP header with every request: X-Permitted-Cross-Domain-Policies none.

The Public-Key-Pins header allows you to whitelist the Certificate Authorities (CAs) it should accept in the future. This protects you against TLS certificates issued by compromised CAs. Here’s more about this topic.

Check your site

There’s a handy security headers service to check your server’s configuration and calculate a rating.