HSTS: Forcing HTTPS for your service

You may have a hard time finding a non-HTTPS site today, but it was not too long ago when the default was HTTP. Sites like Facebook and Google were available without HTTPS/SSL for anyone in the network path to sniff and inject traffic into (even steal passwords and cookies). ISPs in particular loved to know what you were searching for, and loved even more to inject javascripts to show advertisements onto any page you were browsing. Migration towards HTTPS had started a while back and it had a significant impact in reduction of stolen credentials and as a result reduction in online abuse.

Unfortunately, websites still had to keep their HTTP version of their sites running. Not all users had switched to browsers which supported SSL back then. While the sites did automatically redirect supported browsers from HTTP to HTTPS, the redirect was being done using HTTP response header 301. This allowed an opening for an attacker to modify the 301 redirects to keep the browser on the HTTP version of the site.

HSTS to the rescue

HSTS (HTTP Strict Transfer Security) was initially proposed by the IETF as RFC 6797 back in 2012. It was a policy mechanism designed specifically to protect against man-in-the-middle and protocol-downgrade attacks.

While you can read the very detailed RFC to understand why it was designed the way it was designed, the actual implementation of this feature was downright simple.

HTTP Strict Transport Security (HSTS) is a policy mechanism that helps to protect websites against man-in-the-middle attacks such as protocol downgrade attacks[1] and cookie hijacking. It allows web servers to declare that web browsers (or other complying user agents) should automatically interact with it using only HTTPS connections, which provide Transport Layer Security (TLS/SSL), unlike the insecure HTTP used alone. HSTS is an IETFstandards track protocol and is specified in RFC6797.


HSTS policy is communicated by the server to the browser/client using a standard HTTP response header. Once instructed, the browser would be forced to ignore the HTTP end points of the server for a given amount of time. The following HTTP header (if sent as part of the HTTP response) would force the browser to use the HTTPS end point of this service for 1 year.

Strict-Transport-Security "max-age=31536000;"

To automatically protect against all sub-domains of this website, the HSTS policy header allowed one to include the text “includeSubdomains” to enforce HTTPS across all of its properties. Looks like this:

Strict-Transport-Security "max-age=31536000; includeSubDomains;"

There was still a problem with this feature. For HSTS to work, the server has to instruct the client to use HSTS in the response header of the plain-text HTTP session. This allowed an attacker in the middle to strip out HSTS headers to disable the enforcement.

Preloading HSTS

To protect against this attack, the popular browser vendors (chrome included) launched a program to preload the browsers with a list of domains which should only use HTTPS. While this was initially a static list, any website can get themselves included in this preload list by updating their header to include “preload” and using the hstspreload service to register the domain formally.

Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

Once its accepted, this makes its way into Chrome’s preload list, which then makes it way into Chrome and other browsers.

To test this whole thing out, I just enabled HSTS on flagthis.com and by submitting my request into hstspreload service. This is what the submission looks like.

HSTS is just one small piece of the infrastructure which Chrome implements to keep its user data and communications safe from attackers. Kudos to all the browser developers for always staying a step ahead in this very challenging cat and mouse game.






Leave a Reply