How Firefox's HTTPS-only mode solves the first insecure request problem

A change in the browser's default behavior gives a good solution to a tough problem

Author's image
Tamás Sallai
5 mins

HTTPS-only

Firefox recently announced that it will only connect to HTTPS pages and you need to disable it explicitly if you want to use unencrypted HTTP. It's opt-in at the moment and you need to enable it in the browser but hopefully, it will be the default behavior in the future. This change is in-line with the recent shift from positive (padlock) to negative ("Not secure" text) indicators to inform users whether the page they are visiting uses transport-layer security or not.

I find Firefox's initiative a good step toward the secure web as it solves a particularly hard problem: the insecure first request.

The current behavior of most browsers when you enter a webpage (example.com) is to send an HTTP request to http://example.com. This uses an unencrypted channel and flags the page as not secure. Websites then can upgrade the connection to HTTPS by sending a redirect to https://example.com with a HTTP 301 status code. For the end-user, this is an invisible process as it happens automatically.

Modern content delivery platforms make this setting easy. For example, Cloudflare has a dedicated Page Rule that upgrades all requests to HTTPS when needed:

Enforce HTTPS in Cloudflare

Similarly, CloudFront allows enabling the HTTP endpoint for the distribution but only to send the redirect:

Redirect HTTP to HTTPS in CloudFront

With this setup, a visitor gets to the HTTPS endpoint and sees the padlock. This gives a sense of security.

The first request problem

But this setup still makes an unencrypted connection as the browser sends the initial request to the HTTP endpoint and this opens the possibility of a transport-layer attack. If somebody can modify the response, they can keep the visitor on HTTP, which they control, or redirect them to a different site. And all while the website deploys a secure site and does everything to prevent it.

There are patchwork solutions to this problem though. The HSTS (HTTP Strict Transport Security) header tells the returning visitors to use only the HTTPS endpoint. For example, this header tells the browser to remember this setting for 7 days:

Strict-Transport-Security: max-age=604800;

If you visit a site regularly, this makes all your connections go to the HTTPS endpoint. But a site you've never connected to still uses HTTP.

To solve this, browsers started embedding a list of sites that are known to prefer HTTPS connections. This is the HSTS preload list and websites can opt-in with the ; preload extension to the HSTS header:

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

When a site is on this list then the browser won't use HTTP to connect to it, only HTTPS. This solves the first request problem.

As a user, you can use browser extensions that change the default behavior of the browser you are using. The HTTPS Everywhere which is maintained by the EFF uses a separate list of websites, called the HTTPS Everywhere Atlas that fulfills a similar purpose as the HSTS preload list but it's maintained not by webmasters but contributors. Even if the owner of the site does not know about this extension, people can add it to the list, and all users of the extension benefits.

A more universal solution is implemented for example in Smart HTTPS. This makes the browser connect to the HTTPS endpoint first and only if it's unavailable try the HTTP one. If the website is available on the former this behavior prevents any insecure requests. The main flaw of this approach is that it automatically falls back to HTTP, so an attacker can block the HTTPS response then change the resulting HTTP call.

How HTTPS-only works

With the recent change, Firefox makes a request to the HTTPS endpoint only. If it is not available, it will prompt the user if they want to load the page over HTTP.

For webmasters, this means there is no need to open the HTTP endpoint just to redirect users as they won't even connect to it. Of course, it needs that all users use a browser using HTTPS first, but hopefully, we'll get there. This simplifies deployment a bit and it does not rely on complicated solutions like getting on the preload list.

For users, it solves the first request problem for all websites that support an HTTPS endpoint. You no longer need to rely on the webmasters to submit their sites to the preload list nor install any extensions. If the site is available over HTTPS all connections to it will be secure.

If the site is available only on HTTP then it will add an additional hurdle to visit as you need to disable HTTPS-only for that site. This is a strong negative indicator and might push websites to move over to HTTPS. As a user, you have the choice to visit the page knowing it will connect via HTTP.

The more problematic case is when the page loads over HTTPS but it's broken. This can happen when the resources on it do not load via HTTPS or when the site serves different content on that endpoint.

Conclusion

Firefox's move is a bold one but it's definitely in the right direction. This provides a solution to a hard problem, and it makes obsolete the backstop solutions implemented today: the HSTS preload list and the browser extensions.

And what if you do want somebody to intercept and modify the website? Think airports and hotels that redirect to their login page but they rely on HTTP to do this. In this case, use a dedicated page for this purpose.

December 8, 2020

Free PDF guide

Sign up to our newsletter and download the "Foreign key constraints in DynamoDB" guide.


In this article