If you operate a website and want to enable HSTS, you should know about a few caveats:
1. You can't go back! As soon as a browser sees Strict-Transport-Security "max-age=31536000", it will refuse to load your site over HTTP for the next year.
2. The includeSubDomains option can cause problems in hard-to-predict ways. For example, Mailgun lets you set a CNAME for unsubscribe links. If a browser tries to load the HTTPS version, they'll get mailgun.com's cert, which is invalid for your domain.
3. Secure transport doesn't stop XSS, CSRF, etc. There are other headers such as Content-Security-Policy that can ameliorate some of these attacks. Also, sanitize!
4. HSTS is just one part of ensuring secure transport. It's also important to check your cipher suites. Not all TLS is created equal. SSL Labs is an extremely useful tool for testing your config: https://www.ssllabs.com/ssltest/analyze.html?d=floobits.com
If you're curious what the final result of all this paranoia looks like, take a look at the httpd config for floobits.com: https://gist.github.com/ggreer/9984770
You'll also notice mod_authn_yubikey. We require multi-factor auth (YubiKey + password) for our admin interface. There's tons of other stuff I could go into, but the real lesson is that security is like raking pine needles: You will never be done.
You can't go back! As soon as a browser sees Strict-Transport-Security "max-age=31536000", it will refuse to load your site over HTTP for the next year.
This sounds like a powerful way to DOS a site if you can set up a temporary https server on the domain and send this signal.
It's true that HSTS could be a way for someone who can set up a seemingly valid but nonetheless fake HTTPS listener on a domain to prevent people from later communicating with a genuine HTTP service on that domain.
Three remedies for this, with different degrees of applicability to different sites:
* Put a CAA record for your domain into your DNS (see https://tools.ietf.org/html/rfc6844) to prevent legitimate certificate authorities from issuing the cert to the impostor. (This only provides protection if the attacker doesn't control your DNS zone.)
* Actually switch to HTTPS!
* If this attack happens to you and you don't want to switch to HTTPS, run a legitimate HTTPS listener on your domain that clears the HSTS status and then redirects users back to HTTP.
The solution to that is every site should support HTTPS (or at least every site that has even the slightest risk that someone would want to do this to them).
> 1. You can't go back! As soon as a browser sees Strict-Transport-Security "max-age=31536000", it will refuse to load your site over HTTP for the next year.
Is this true? What if you send a new header with a max-age of 1 second, or send one with a garbage value?
I'm pretty sure I've seen a way for a website to disable HSTS, but I can't confirm right now.
Yes, but you'd have to serve that over HTTPS. And even then, how do you know that all the caches that have the older, longer expiration time have revisited and updated their cache? You won't, really, until that many seconds have pass.
Right, my point was just that there is a specified way for the server to tell the client not to use HSTS any more. Of course, the caveats you mention mean that to be certain, you would need to wait.
You can't go back in the sense that random end-users that visit your site will likely have that cached. In chrome, you can always visit about:net-internals and clear the HSTS cache. Probably not useful for random users, but good to know if you've found yourself locked out of something after messing around with settings.
If a site sends max-age=31536000 and then subsequently sends max-age=3, does the second header overwrite the first? If so, then you can in fact go back as long as you're willing to continue supporting HTTPS until the longest max-age header you ever sent has expired.
Of course, it would help if browsers stopped letting sites put an image at the same place they show the locker (like they used to)... But that would require a few more pixels for canvas, and security is a secondary concern (just like usability).
Can't a MITM (as described in the article) strip out any HSTS headers automatically, thus thwarting this quite simply?
As with HTTPS, you need a shared secret before communication begins for anything like this to combat MITM attacks. Unless the browser communicates with a secure server to assess whether the website should be sending HSTS headers... Is that the idea?
On the very first connection from the browser to the website, yes. But the browser saves the HSTS setting (for the time specified by the HSTS header's max-age value) so future connections go straight to HTTPS.
It seems silly that Chromium and Firefox now have separate HSTS lists (though Firefox's was seeded using the Chromium list [1]).
At the moment, these lists appear to be b) tied to specific browsers 2) tied to specific releases of those browsers.
Would it be viable to run some kind of global open registry where any website can be registered for mandatory HSTS? That way, every individual website owner doesn't need to submit a bug to Chromium and Mozilla - the browser just needs to securely connect to the registry and download the latest list. Or maybe DNSSEC can help ...
Maybe work on this is already underway, but I was reading some MLs a few weeks ago and I didn't see any forthcoming solutions ...
I believe that Firefox is still generating its HSTS preload list from Chromium's - a few months ago I got a site added to Chromium's HSTS list and a few weeks later it showed up in Firefox. I couldn't even figure out how to submit directly to Firefox.
I agree that a global registry would be better, but it should probably be updated using the browser's normal update channel, to avoid re-inventing the wheel. (And DNSSEC has way too many issues.) It's true that ties the list to specific releases, but since browsers have good, and frequent, auto-updating, I think that's OK.
Ok, so how about the attacker intercepts the https request with a self-signed cert, modifies the stored HSTS header by issuing a new max-age of 0.25 second, and includes a redirect back to http://?
This just kind of seems unwinnable, a million holes.
> Ok, so how about the attacker intercepts the https request with a self-signed cert, modifies the stored HSTS header by issuing a new max-age of 0.25 second, and includes a redirect back to http://?
HSTS disallows the user from overriding the certificate warning and accepting a self-signed cert.
(You just edited your comment, didn't you) Well, that's a good detail then.
Does it in fact reject connections to self-signed certs? Or just disallow you from accepting the broken cert? Because the real goal would just be to get the user onto http:// as quick as possible, and then the untrusted warning is gone.
(You keep editing your comments, replacing old questions with new questions, which makes it rather difficult to reply to you. I suggest making new comments instead.)
> Does it in fact reject connections to self-signed certs?
Yes, you don't even need HSTS for this. HSTS just disallows the user from overriding the browser and accepting the self-signed (or otherwise bad) certificate.
> But an attacker can certainly intercept HTTPS as well, and if they redirect you quick enough you'll never see the "wrong cert" errors.
No, any sort of HTTPS interception will be detected by the browser (assuming of course that the certificate authority infrastructure has not been compromised). There's no way to redirect "quick enough" to bypass certificate checking.
Of course it is detected, we are not trying to fool the PC. When I visit my personal website with a flawed certificate (for example, once I was missing the Intermediate CA) it loads the site all the same, but the lock icon shows a security verification failure.
What in HSTS protects you from that? Because it seems to me if you can get there, you can get back to http:// before the user notices the verification failure. Unless the browser simply refuses to load the site due to the verification failure, which I only see for "suspected attack sites"
Intercept 443 => Issue insecure page with new HSTS timeout => Redirect to 80 before user notices insecure page warning
But it only loads because you added an exception at some point in the past. On any normal site, it would show you a cert error and wouldn't load the page at all.
For that to work they would have to have access to the browser since the headers would be sent over TLS/SSL after the first connection. If they've got access to the client's machine and browser all bets are off. They could install their own CA and MITM even if the site is using HSTS. Certificate pinning would help solve some of that problem but you might not be able to trust that on a compromised machine anyway.
This whole attack is assuming the attacker is there from the very first packet of the particular login session. Not about inserting a MITM in the middle of an established login session.
The initial connection of an intercepted HTTPS connection would throw a security error, because the attacker would be using the wrong cert, but if you redirect the victim quickly...
You can defeat this particular hole by getting more aggressive about untrusted certificates, but it seems browsers are very reluctant to do that.
One interesting thing I've noticed about HSTS (which is probably a good thing in the long run, but kind of painful for now): it breaks wi-fi capture-portal redirects. Try to load https://news.ycombinator.com/ on a fresh connection to a wi-fi hotspot, and you just get a connection error.
Some people have been thinking about creating a standard to distinguish between the two so that captive portals won't have to do a MITM attack (that browsers currently correctly defend against). One idea might be to have a different protocol through which the captive portal can indicate its presence and declare itself as a captive portal, entirely or almost entirely outside of the HTTP or HTTPS session.
Getting the UI right is pretty challenging, though. It's not even completely clear what getting it right would mean. Even if the user clearly understands that they're interacting with some network operator rather than, say, Gmail or their organizational webmail server, the user still has no way to know whether the portal they're talking to is actually operated by the operator of the network that they think they're connecting to!
Chrome does this already by sending a hidden request to http://www.gstatic.com/generate_204 and displaying the page in a new tab if the request is intercepted.
I've wondered this too. Doesn't DHCP support extensible options? Couldn't you just send an option that said, "hey, crappy portal welcome site at {URL}"? It'd be fixed to a particular webpage (so, you can't use another protocol), but that's the state of things today.
It seems like there are only two things captive-portals are "for", though: accepting EULAs, and presenting a login form for the proxy. Both of these could be better if built into browser/OS chrome.
I would like to point out that HSTS is not compatible with private browsing because by saving the information that the particular site must be accessed by HTTPS the browser exposes the fact that the said site was previously accessed. I hope we will eventually come to required secure HTTP by default with the next versions of the protocol.
Briefly: a page can embed a hidden image with a http:// URL (with a different hostname, used just for tracking purposes). If that image gets loaded over HTTPS, it means the site has been visited before. If it loads over HTTP, the site hasn't been visited before; it then redirects to the HTTPS version and sends a HSTS header so on the next visit it goes straight to HTTPS.
That stores one bit of information. Repeat 32 times (with 32 different host names) and you can store a unique 32-bit tracking number that persists even when cookies are cleared.
The real drastic solution is to disable HTTP for the entire internet and stop implicitly trusting the identity of servers. Until we decide that is worthwhile we're just going to be patching a leaky boat.
Alternatively, make a plain html website and don't ask users to log in and don't track them with cookies, etc. If you want to collect money from them, make a real product and mail it to them after they sent you a postal money order.
Note that if you take their money and don't ship their product as described, the US Postal Inspection Service will come after you. It protects both sides from fraud.
HTTPS sounds great and st but HTTPS won't help you if you dumb enough to execute shell commands as a root on your server based on unfiltered user form inputs... Unfortunately, I noticed that lots of 'idea guys' trust the dev they hire first even if they have absolutely no skills whatsoever. lOOOl
1. You can't go back! As soon as a browser sees Strict-Transport-Security "max-age=31536000", it will refuse to load your site over HTTP for the next year.
2. The includeSubDomains option can cause problems in hard-to-predict ways. For example, Mailgun lets you set a CNAME for unsubscribe links. If a browser tries to load the HTTPS version, they'll get mailgun.com's cert, which is invalid for your domain.
3. Secure transport doesn't stop XSS, CSRF, etc. There are other headers such as Content-Security-Policy that can ameliorate some of these attacks. Also, sanitize!
4. HSTS is just one part of ensuring secure transport. It's also important to check your cipher suites. Not all TLS is created equal. SSL Labs is an extremely useful tool for testing your config: https://www.ssllabs.com/ssltest/analyze.html?d=floobits.com
If you're curious what the final result of all this paranoia looks like, take a look at the httpd config for floobits.com: https://gist.github.com/ggreer/9984770
You'll also notice mod_authn_yubikey. We require multi-factor auth (YubiKey + password) for our admin interface. There's tons of other stuff I could go into, but the real lesson is that security is like raking pine needles: You will never be done.