Security Tip: How Strict Is your Transport Security?
[Tip #82] HTTPS is everywhere & easy, but HTTP is still an option... How do you stop an attacker intercepting and downgrading connections to your site?
Last week we looked at the Referer
security header, so we've moving onto another header this week: Strict-Transport-Security
.
The HTTP Strict-Transport-Security
(HSTS) header informs the user's browser that the current site should only be accessed via HTTPS - preventing it from loading the site via HTTP entirely.
This is an important header to pay attention to, as it's designed to prevent Downgrade attacks via a Person in the Middle (PitM/MitM) attack on the connection.
Normally the connection from the Browser looks like this:
However, if the Attacker can intercept the request, they can tell the Browser to use HTTP only, while maintaining the HTTPS connection with the Server themselves:
This allows the attacker to read and modify all requests passing through. This means they have full access to passwords, payment details, private or sensitive information, etc, as well as make any changes or run any commands on the compromised site.
The Strict-Transport-Security
header prevents this attack by telling the Browser it requires an encrypted HTTPS connection. If the Attacker (or Server) tries to use an unencrypted HTTP connection, the Browser will reject it and display a warning instead. It will always require a valid encrypted HTTPS request, and block or ignore any redirects or attempts otherwise.
Since an attacker could easily strip out the header, the browser remembers it after the first time it sees it for max-age
seconds. This allows the browser to reject any future unencrypted HTTP requests (within the max-age
) automatically, keeping the site protected.
For example, this instructs the browser to require HTTPS for 1 year:
Strict-Transport-Security: max-age=31536000
Adding the includeSubDomains
directive instructs the browser to apply HTST to the domain and all subdomains for 1 year, allowing the first request to anywhere on the domain to store the HSTS requirement.
Strict-Transport-Security: max-age=31536000; includeSubDomains
How Long For max-age
?
Most sites should only be accessed via HTTPS, so going for a long expiry of 1-2 years is recommended. This keeps the site protected across infrequent visits.
That said, if you have an older domain, with a bunch of different subdomains, hosting different apps, you may have some areas that need HTTP only. If you're worried about this, you could start with a short max-age
to see if anything breaks and slowly work up. I.e. 5 minutes, 1 day, 1 week, 1 month, etc. However, this is becoming much less common as HTTPS is much easier than it used to be, and browsers are actively warning users on HTTP sites.
Preloading, aka the Trust On First Use (TOFU) Problem
You may have spotted one of the downsides of the HSTS header already: the browser gets the HSTS header on the first request.
This means if an attacker is already intercepting traffic, they can strip the header while downgrading to HTTP to prevent the Browser from knowing it should have an encrypted connection.
This is called the Trust On First Use (TOFU) problem.
HSTS gets around this with the preload
directive and the Preload List. The Preload List is a list of hardcoded domains within the major browsers (Chrome, Firefox, Safari, etc), which lists all of the domains which require HTTPS. The browser will not make an HTTP request to these domains, preventing an attacker from intercepting any requests or attempting downgrade attacks.
To get your site on the Preload list, you need to enable HSTS with max-age
of at least 1 year, include subdomains with includeSubDomains
, and add the preload
directive.
Once that's live and working, you can submit it to the Preload List at hstspreload.org, and it will be included in browsers in a future release.
Note: Removal from the Preload List may take months or even years. So make sure you're aware of the implications before adding preload
and submitting your domain.
Some newer domain extensions, notably .dev
and .app
, are already included in the Preload List, which helps enforce security of any apps that use those extensions. So if you're using one of these, you're already protected. 🙂