HTTP Strict Transport Security — Why you need it, five common mistakes and how to fix them.
THE POWER OF HTTPS
Encrypting connections to websites by using HTTPS is an extremely powerful way to increase the security provided to users visiting them. It prevents web traffic to be intercepted, modified, or redirected. It provides a level of authentication. Additionally, it protects the integrity and confidentiality of the data being served.
As an added benefit, transport layer security is rarely directly tied into the inner workings of an application. Though there are certainly cases where switching to HTTPS is considered a challenge for technical reasons, this is not the rule. Even applications that have not seen updates in years can often be served via HTTPS without any or with minimal changes. Of course, this does not change anything about the security problems such an application may have on a different level. Encryption will not save you from a lack of input validation and the consequences that stem from it. But it is a comparably easy way to reduce some of the risks in a common threat model for consumers: using untrusted networks in public places, ISPs tampering with net neutrality, employers snooping on their employees.
Because using HTTPS offers a quite reasonable cost/benefit ratio, it has become heavily incentivized. Google is giving a ranking boost to secure sites since 2014. Let’s Encrypt is a public benefit organizations founded by a variety of heavy-hitters such as the Electronic Frontier Foundation and the Mozilla Foundation who has reduced the — once quite costly — price for SSL certificates to “free”, making transport encryption a feasible solution for a way larger target audience. It is becoming harder and harder to find an excuse to not use encryption. In fact, not using HTTPS now results in adverse effects: Browsers, such as Chrome, will now label sites served via an unencrypted HTTP connection as insecure.
ATTACKING THE ENTRY POINT
Because of all these aspects outlined in the last section, the usage of HTTPS has skyrocketed in the past years. This is not primarily to the credit of site owners, but mostly due to the easier tools that are at their disposal to enable HTTPS for their site with just a couple of mouse clicks and very little technical knowledge.
Yet, HTTP is still common. Some websites still serve their entire content unencrypted and do not offer HTTPS. While unfortunate for sites serving static content, which run the risk of having malware or other undesired content injected into them in transit, this is downright reckless for sites that feature any form of login or similar mechanisms. Sadly, this still exists.
The HTTP/HTTPS hybrid site is disappearing slowly. These sites use HTTP for content deemed unproblematic, but switch to HTTPS for more delicate parts, such as login forms. A very common vulnerability in this type of site was the delivery of the login form via HTTP, which effectively allowed an attacker in a man-in-the-middle (MITM) scenario to change the
action attribute of the form and harvest credentials at their leisure. In the full knowledge that there might be valid scenarios where this approach is useful and necessary, it can clearly be stated that this constitutes going through a lot of trouble for what could often be handled way simpler by just using HTTPS on the entire site.
But even sites served fully encrypted via HTTPS (tcp/443) will still run a webserver on HTTP (tcp/80) to redirect users to the secure version of the site. HTTP is not going anywhere soon. And this situation still has some notable risks.
To illustrate this, think about a user wanting to access the content served by https://www.example.com. Assuming they are not using a search engine to get to where they want to go, they will click the address bar of their browser and enter “www.example.com”. Traditionally, this will lead the browser to assume the scheme is “http://” and to try connecting to the web server listening at www.example.com on port 80. This will happen in most cases, unless the browser already knows there is a secure version of the site to be preferred. We’ll get to that.
This is a vulnerable moment in the process. If an attacker is intercepting this connection, there is nothing stopping them from redirecting the connection to https://www.example.net, a duplicate of the site controlled by the attacker. Note that in this example, the attacker is using HTTPS to serve their website and might use a valid certificate for example.net issued by LetsEncrypt or another Certificate Authority (CA). The responsibility of CAs with regards to phishing sites has been debated at length, but the short version is: A domain validation certificate asserts that a public key belongs to a domain, not that the owner are who they claims they are. This stands in contrast to Extended Validation (EV) certificates, who — at least in theory — do identify the legal entity owning a site. However, a study called “An Evaluation of Extended Validation and Picture-in-Picture Phishing Attacks”: http://www.usablesecurity.org/papers/jackson.pdf by Microsoft Research and Stanford University in 2006 concluded that “participants who received no training in browser security features did not notice the extended validation indicator and did not outperform the control group.”
In the scenario of a rogue www.example.net, a user’s sole realistic chance would be that the site they are being redirected to is a known threat that is detected by, for example, “Google’s Safe Browsing API, resulting in an warning message”: https://testsafebrowsing.appspot.com/. There is a chance that the user will notice the change of the TLD, but it is way less likely after they manually entered their destination and has little reason to question the legitimacy of the response.
ONE HEADER TO BIND THEM ALL
The usage of security headers has been discussed at length on this blog alone. The various available headers vary in ease of use and effectiveness. However, few are as effective and simple to use as HTTP Strict Transport Security (HSTS).
So what does HSTS do? Let’s look at a sample header:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Once received, the browser will remember that the site sending this is only to be contacted via HTTPS. Any future attempts to use HTTP will result in an immediate, client-side redirection to HTTPS. Additionally, “RFC6797”: https://tools.ietf.org/html/rfc6797 strongly recommends that users should not be able to click through warnings about invalid certificates. This means that an attacker performing a MITM attack will providing a fake certificate will have no chance of the user making the wrong decision of accepting an invalid certificate based on a lack of experience or knowledge.
This sample header contains the three directives available:
max-age=<delta seconds>: defines the time-to-live of the effect HSTS has in seconds.
includeSubDomains: extends the validity of the HSTS to all subdomains of the same domain, so for example.com, this would mean that sites such as my.example.com are also be requested via HTTPS.
preload: a special case, as it is not described in RFC6797. It states the sites intention to be included in a list of sites that use HSTS, so even for first-time visitors, HSTS would be enforced. This requires the site to be manually submitted for inclusion in the HSTS Preload List.
When used correctly, HSTS does fill the security gap of accidentally connecting to an HTTP server and being redirected by an attacker. Even if
preload is not set: When
max-ageis sufficiently long (see below), at least returning visitors’ browsers would thwart such an attack. It should be abundantly clear that the
Strict-Transport-Security header should be set for every website offering an HTTPS connection, as its benefits severely outweigh the effort required and outweigh known challenges and issues.
Once set up, the
Strict-Transport-Security header is quite low in terms of maintenance. However, there are a few common mistakes often observed in the wild. Here are the five most common ones:
A Strict-Transport-Security header is served via HTTP
A HSTS header persistently alters the way a site is treated by the browser. As such, it needs to be sent over a connection that is considered secure. If a request is sent via HTTP, the browser should issue a 301 status code along with a
Location: header redirecting to the HTTPS version of the site that will also serve the HSTS header. RFC6797 explicitly states that browsers are to ignore HSTS headers sent over non-secure connections. Doing it anyway will most likely do no damage, but it has no positive effect either.
max-age is set too low
A common recommendation for production sites is to set
max-age to 31536000, which constitutes roughly a non-leap year. Lower values can be useful for testing purposes but increase the frequency a window of attack occurs due to the expiration of the header. It takes little effort to find examples of sites using values as low as one minute. This defeats the purpose of HSTS and does, worst case, convey a wrong sense of security because the site has – strictly technical – a valid HSTS header.
max-age is set to 0
max-age to 0 instructs the browser to remove the cached HSTS policy for this host immediately, including the
includeSubDomains directive (if applicable). From a security perspective, this is unwise. Therefore this point is listed here as a misconfiguration. As a relevant side note: websites setting HSTS
max-age to 0 might be abusing HSTS in order to track users.
You want to serve all your content via HTTPS. That includes your subdomains. But that is not the sole reason for this being relevant: subdomains can manipulate cookies, potentially opening up a variety effects. Whenever possible, setting
includeSubDomains is highly recommended.
preload is not used (correctly)
preload is not an official directive. And it is the one that can effectively have adverse consequences. Should you ever choose that you want, in fact, serve HTTP content or use a self-signed certificate, you will be in hot water. Because the preload list is shipped with browsers, it will take some time to get your site removed, usually 6-12 weeks for mostChrome users and potentially longer for users with other browsers. If you are aware of the potential consequences and how to avoid them, using
preload is a good option. However, it is often overlooked that adding the
preload is not sufficient to get included in the preload ist. After all criteria are met, the site needs to be submitted via hstspreload.org after which it will be included in the list after weeks – or longer.
Is has become simpler and simpler to use HTTPS in order to offer users a secure way to communicate with a website. Using HSTS requires slightly more effort but reduces residual risk significantly. Using the links and comments in this article, you should be well-equipped to deploy HSTS to your site, fix current shortcomings and provide appropriate guidance to others who want to do the same.