Quick Guide to Security Headers - Part Two
In our last post, we explored 3 of the most important security headers: Content-Security-Policy, Strict-Transport-Security and X-Frame-Options. In this post, we’ll review four additional security headers and then wrap up our discussion.
This header only has one option: nosniff. Although it’s quite simple to implement (“X-Content-Type-Options: nosniff”), the logic behind why you’d want to incorporate this header is nuanced.
We take advantage of this type of behavior frequently when client web applications improperly sanitize user file uploads.
To prohibit this behavior, we need to block MIME type Sniffing via the X-Content-Type-Options header.
When a link is followed on a webpage, whether by a user clicking a link or a resource loading in the background, the browser will send client request information to the target server. Of most concern is the “Referer” value. Yes, I know it’s spelled incorrectly. That’s just how it is. Interestingly, “Referrer-Policy” is spelled correctly. It’s annoying. Oh well.
Anyway, when your browser sends the target server your “Referer” information, it sends the URL that you’re making the request from.
The “Referer” header potentially leaks sensitive information. It’s possible just disclosing the URL you’re coming from is a security issue. A more troubling case is when the entire URL is sent and leaks important information, like a password reset token.
There are many different options for the “Referrer-Policy” to help combat these issues. The most strict option is “no-referrer”, which will omit the “Referer” header completely. Please review Mozilla’s documentation to determine which of the 8 options makes the most sense for your web application.
According to Mozilla’s documentation, this header is currently still in an experimental state and will change over to the name “Permissions-Policy”. The idea is to explicitly allow or deny the use of specific “Directives” in the browser. What is a “Directive”? There’s a long list located here. As an example, the accelerometer, autoplay, camera, gyroscope and full screen features are all considered directives. To use the header to deny the use of the autoplay feature, for example, you set the policy: “Feature-Policy: autoplay ‘none’”.
Why is this important?
If this only applied to content directly coming from your site, it might not be that interesting. But the “Feature-policy” header allows developers to block any directive usage from within an embedded iframe. This protects your users by blocking iFrames from conducting potential privacy-violating activates such as enabling the user’s microphone or grabbing their geolocation information. This article breaks this feature into much greater detail.
Check out the documentation to see if these would be useful for your application.
So, you know the headers you want to use. How do you implement them? Well, you have two options: within the web application or on the server. By far, implementing security headers on the server is more common. There are a ton of articles about how to specify content security policies and enforce strict transport security on Apache, Nginx and IIS servers. However, you can also implement these policies at the application layer. We’re big fans of Python Flask at FortyNorth Security and implementing security headers is simple. Here’s an example from a repo:
If for whatever technical reason you decide to implement security headers at the application level, ensure that any additional/replicating security headers at the server level don’t contradict your work within the application.
How can I tell how good our policy is?
Huge shout out to @Scott_Helme for creating the site SecurityHeaders.com. For nearly all of our web application assessments, we’ll run our client’s domain(s) through securityheaders.com and screenshot the site grade to provide our clients with a baseline for their security headers posture.
Pen testers, add this into your project checklist. Web application developers, throw your site in here to generate a baseline.
We’d be remiss if we don’t mention that although they are not headers per-se, consider other server and application security configurations, like setting cookies for secure and httpsOnly.
Generating HTTP security headers is an iterative and evolving process. Your first round of security headers might work today, but as your application grows and changes, you’ll need new/amended headers. Also, over the last few years, we’ve seen new types of security headers pop up and I guarantee we’ll see more in the future. Keep watch for new headers and evaluate whether they make sense for your web application.
And when in doubt, just contact us and we’d be happy to review your security header’s posture.
By: Joe Leon