Hi everybody! So, after some feedback about the last “quick” Quick Bites (thanks Josh!), I’ve decided to try to keep this one shorter. You know, make it an ACTUAL “Quick” bite. So, without further ado, I bring you Quick Bites Episode 2 - HTTP Security Headers and Why You NEED Them. Let’s jump in, shall we?
What are HTTP Security Headers again?
Below is an HTTP request to https://www.professionallyevil.com/. Note all the HTTP request headers that are sent from the browser (the headers are on lines 2-16). Bonus points if you can tell me what browser I’m using!
Below is the HTTP response from https://www.professionallyevil.com/ . See how there is an entirely different set of HTTP headers in the response (lines 2-15)? These response headers are the ones that we’re focusing on in this article. Well, not these SPECIFIC headers, but the HTTP response security headers. Ahem. Yeah, just please keep reading.
OK, now I’ve seen some HTTP headers. Why do I need them?
Why, I’m glad you asked! Some of these headers provide the browser with bits of non-security related information. Others help prevent certain types of attacks such as cross-site scripting (XSS), cross-site request forgery (CSRF), protocol downgrade attacks, and others. These headers are actually quite important, but we still see them missing during web application tests which weakens the overall security of the applications. Modern browsers are equipped with the ability to understand and work with the majority of HTTP headers, so implementing them is really a no-brainer. To start, here’s a list of some of the headers, in no particular order.
Content Security Policy
Content-Security-Policy: script-src 'self' frame-ancestors 'self' img-src '*'
HTTP Strict Transport Security (HSTS)
This header specifies that the browser can only access content for the webapp through the HTTPS protocol. Simple. Oh, it also specifies that the browser should load the website through HTTPS for a specific amount of time (set in seconds). Note that the max-age directive is *required*, while the includeSubDomains directive is *optional*. The header essentially prevents a browser from connecting to a webapp without encryption enabled. This helps keep man-in-the-middle attacks from downgrading traffic to plaintext HTTP.
Strict-Transport-Security: max-age=31536000; includeSubDomains
This header helps prevent clickjacking attacks. It tells the browser whether or not the page being loaded can be rendered within a <frame> or <iframe> HTML tag. This basically prevents an attacker from embedding a page inside of an iframe on a malicious site, which can then perform an action on the clicker’s behalf. It’s not necessarily a major security issue, because it’s rare, but it’s worth including here.
X-Frame-Options: ALLOW FROM https://www.professionallyevil.com
Caching web pages has long been used as a way to keep web traffic to a minimum. Sometimes, there’s some really sensitive information (think credit card numbers or passwords) stored in that cache, particularly for web browsers. If an attacker can gain access to that cache, then that sensitive information can be stolen, and used for fun and profit. The Cache-Control header limits the cache that is stored by the browser, by only keeping it for a certain period of time or disabling the cache for that site altogether.
Cache-Control: max-age=604800, must-revalidate
When you surf a website, your browser performs a few tasks in the background. Images, scripts, and other files are loaded and presented in the browser. The web server typically sets the MIME type with a Content-Type header, which the browser can then interpret to present. For example, an PNG image will have a MIME type of image/png, which can instruct the browser to render the PNG file. However, sometimes, these files are set incorrectly, which forces the browser to “sniff” the file to determine what it is. This is called MIME sniffing.
To mitigate this, the X-Content-Type-Options security header can be added to the page forcing the browser to render the file as the Content-Type header intends, preventing MIME sniffing attacks.
The End… ?
It's important to remember that many of these HTTP response headers provide directives to the browser's built-in security controls. So when we perform a web application penetration test, we will examine these headers to determine which browser controls were left open. This analysis hints at what attack scenarios are more likely to succeed against the web application. With that being said, there are several other HTTP security headers that can be implemented, but what and how they’re used is left as an exercise for the reader. If you have any questions, check out the References section of each header, or you can simply reach out to us - we’re happy to help.