What is HSTS?

Hussein Nasser
4 min readJan 8, 2020

--

We are a single unencrypted HTTP GET request away from getting MITMed. Think about it, If I can see the host you are consuming and you are not asking me to verify myself that is the jackpot for attackers.

In this post, I want to go through how the browser decides what protocol to select for communication HTTP vs HTTPS. I also want to talk through a little bit of the danger of plain HTTP especially in 2020 and how HSTS can help -a little- and finally why HTTPS Everywhere should be on your browser too.

The danger of Naked HTTP

In your browser address box, you type in bankofamerica.com and hit enter. The browser will assume you want http://bankofamerica.com. I can MITM your unencrypted HTTP request, see you want to go to bankofamerica.com and instead reply with a 301 response that bankofamerica.com has moved permanently to https://bankoffamerica.com and ask you to redirect.

I own bankoffamerica.com and guess what; I also secured it with lets-encrypt. So yeah, you will see a padlock on your browser and I have all the HTML and CSS from the original bank of America website on mine as well so Nothing to suspect huh? Well, if you have good eyesight you will immediately see there is an extra f in the host. And you might actually click on the certificate and verify that it is not issued for bank of America.

Note: Most MITM attacks take place at layer 2 on the OSI stack. For example in a public WIFI, an attacker can pretend to be the network router by poisoning the ARP table with broadcast requests telling everybody in the network that its mac address is the actual gateway ip. So any requests to the gateway (which are pretty much all requests) will go to the attacker first, then it will forward it to the actual router.

Why not always communicate in HTTPS then?

Here is the problem, because you typed “bankofamerica.com” in the browser address box, you gave the browser an option of what protocol to use. Browsers will always favor the user experience, so they always communicate in the HTTP protocol because they have no idea if the host supports HTTPS. If browsers always communicated with HTTPS (basically HTTPS Everywhere extension) the user experience will suffer on websites that don’t support HTTPS. In technical terms, the attempt to establish a TCP socket to port 443 port will fail.

But I always see the padlock 🔒

You might say, Hussein, yes I do type in bankofamerica.com or even http://bankofamerica.com but I still see the padlock. That means somewhere along the way my protocol has been upgraded to HTTPS.

Correct, your initial request is http://bankofamerica.com which sends the unencrypted GET request, if that request reached Bank of America safely, their website will respond with this.

Hey, what’s wrong with you? never communicate with us using plain HTTP. Put some pants on, here, go to https://bankofamerica.com.

That is usually done through a 301 response. This will force the browser to close the TCP connection on port 80 and establish a new TCP socket to port 443, initiate TLS session and resend the GET request again. This time encrypted.

If you instead typed https://bankofamerica.com into your browser address box, your session will be immediately encrypted.

HSTS to the Rescue?

HSTS, HTTP Strict Transport Security, would have forced you to use HTTPS. Well, sort of. Let me explain

Modern browsers keep a list with all known websites that only want to communicate in pure HTTPS leaving no room for MITM attacks, SSL Stripping or anything of that sort. Examples of such websites are google, yahoo and yes even bOfa might be even there. This is called the HSTS preloaded list. If you type bankofamerica.com in your browser address box, the browser will look in the HSTS list and if bankofamerica.com is there it will use the HTTPS protocol to communicate, encrypting the session immediately.

The problem with HSTS list is it doesn’t have every website that supports HTTPS. So if you want your website to be on the list, so all clients communicate with HTTPS only, your web server can use Strict-Transport-Security header to tell the browser to update that list. That is not enough though, the first request will always be unencrypted so your users could still be vulnerable.

HTTPS Everywhere

If you are paranoid, use HTTPS Everywhere and turn on the Encrypt All Sites Eligible is ON option. This will not give the browser a choice between HTTP & HTTPS, it will instead always use HTTPS You are better off using HTTPs.

Although HSTS and HTTPS Everywhere will protect you from the obvious easier attacks, it cannot protect you from TLS level attacks. That is when you really need to look at your certificate.

I have an open issue on HTTPS Everywhere github repo for an option to force OCSP Stapling request validation. Again back to favoring user experience browsers will relax certificate validation in certain cases, this will ensure that the user always communicates with a server with a valid certificate.

I’m a terrible writer. I think do better on video, check out my YouTube channel where I discuss HSTS in-depth and other software engineering content.

--

--

Hussein Nasser

Software Engineer passionate about Backend Engineering, Get my backend course https://backend.win