Enabling HTTP Strict Transport Security on debian servers
Posted by dkg on Thu 16 Dec 2010 at 10:48
I just enabled HTTP Strict Transport Security (HSTS) markers on a bunch of web servers that offer HTTPS.
It's an easy step to take, and it means that users of HSTS-compliant browsers (such as Chromium and the upcoming Firefox 4) or browsers with HSTS-compliant extensions (like Firefox's NoScript or HTTPS-Everywhere) will no longer be vulnerable to attacks like sslstrip once they have made one successful connection to the HSTS-enabled HTTPS web site.
It's not a perfect solution, but it is far better than the current situation. And it's easy to implement for websites that already use HTTPS.
For sites using apache, just enable mod_headers (on debian, that's: a2enmod headers) and add the following line to your HTTPS vhost stanza:
Header add Strict-Transport-Security: "max-age=15768000"Depending on your setup, you may want to add the semicolon-delimited argument includeSubdomains, like this:
Header add Strict-Transport-Security: "max-age=15768000;includeSubdomains"(note that the number of seconds above is roughly 6 months -- this is the duration that compliant clients will retain the protection).
If you're using nginx, just add this line to your host configuration:
add_header Strict-Transport-Security max-age=15768000;See also Wikipedia's helpful page on HSTS for more examples.
Happy Hacking!
Let's say you access mymailprovider.com every day, every day you would follow the redirect. But one day you are at a friend's house and his router intercepts your requests using a man in the middle attack and sniffs all your traffic.
If the server would have used STS your http lib would have made a secure https connection in the beginning. Except of course of your very first request on the first day.
[ Parent | Reply to this comment ]
In other words, having the web server redirecting each HTTP request to HTTPS is only okay to secure connections in an already secure environment.
[ Parent | Reply to this comment ]
Currently our server responds to all incoming http connections with a 301 redirect to the same url using https. If I understand sslstrip correctly: in this scenario a man in the middle would modify our redirect to one of his servers to maintain man in the middle. As we redirect _all_ incoming http traffic our attacked user would see a different url in his browser (if he cares to look there, of course).
HSTS would prevent this attack as the server's answer does not provide a different url but only tells the client to use https on the otherwise same url. Thus the attacker cannot redirect to another server.
So now here is the part that I don't understand: if the attacker is a man in the middle, why doesn't he simply strip out the HSTS-header and forwards incoming http traffic in an own https connection to our server?
Is my conclusion correct that HSTS only provides security if the very first http request is not intercepted by that attacker? Of course this would still be a great security improvement e.g. for portable devices that connect the first time to our servers via a secure connection and can afterwards be used securely in foreign networks without the user always having to type https.
Thanks for bringing this interesting topic up and thanks for your help!
[ Parent | Reply to this comment ]
[ Send Message | View dkg's Scratchpad | View Weblogs ]
Currently our server responds to all incoming http connections with a 301 redirect to the same url using https. If I understand sslstrip correctly: in this scenario a man in the middle would modify our redirect to one of his servers to maintain man in the middle. As we redirect _all_ incoming http traffic our attacked user would see a different url in his browser (if he cares to look there, of course).Actually, with a successful sslstrip attack, no change in the address bar is seen. The user types in example.com, and the browser stays at http://example.com because the MITM is acting as a proxy. The MITM accesses https://example.com directly, and serves the returned content back to the user over plain HTTP. The sslstrip tool is also clever enough to re-write all internal https links to http, and can even inject a favicon that looks like a padlock so the browser "shows a lock" even though it sees no HTTPS (here is an example of how this looks).
Is my conclusion correct that HSTS only provides security if the very first http request is not intercepted by that attacker?Yes, you've got it right. HSTS instructs browsers to never use cleartext when re-connecting to a given site for the duration of the max-age parameter. And the header is ignored by browsers if it is sent over plain HTTP (because otherwise, an attacker could use it to trigger a denial-of-service against a web site that doesn't offer HTTPS). So it only protects from the first successful secured connection going forward.
Still, that's a much smaller window of vulnerability than the current situation, particularly for people who regularly use the same browser profile and don't switch machines often.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
Steps:
1. Set the required header in server configuration. I'm using Apache, and the article neglects that this needs header needs be sent for the HTTPS site, _not_ the HTTP site.
2. Check the header is sent. It is: curl -i --insecure https://my.rhombic.net | grep Strict. Yes, I've an expired, self-signed SSL certificate… would that cause problems? Should it? My understanding is that HSTS should not consider certificates at all.
3. Go to https://my.rhombic.net/. Browser should remember the HSTS header.
4. Go to http://my.rhombic.net/. Browser should send you do the HTTPS site automatically; it doesn't, and you see a page you're not supposed to see.
What are other people's experience?
[ Parent | Reply to this comment ]
[ Send Message | View dkg's Scratchpad | View Weblogs ]
You're right that the header needs to be set for HTTPS; reasonable implementations should discard HSTS headers received over insecure transport to avoid a potential denial-of-service attack against insecure web sites. the spec says:
If an HTTP response is received over insecure transport, the UA MUST ignore any present Strict-Transport-Security HTTP Response Header(s).
I wonder if your browsers are interpreting the caveats here subtly differently than mine are:
[...]and there are no underlying secure transport errors or warnings, the UA MUST [...]To my mind, if the user has explicitly made a security exception for the certificate would mean "there are no underlying secure transport errors or warnings", but perhaps the authors of FF4 and/or Chromium have different interpretations.
What do you think should happen in that case? If you think the spec needs clarification, it might be worth writing the authors of the draft to make suggestions.
[ Parent | Reply to this comment ]
Hrm, I do think Firefox 4 and Chrome are stricter about implementing those caveats. I'm not sure I agree… if the certificate has already been accepted by the user, then the browser's HSTS implementation should respect that. I suppose they went for "security" rather than usefulness: is it better to disregard a user's explicit preferences, or assume users are stupid and/or lazy and unable to understand and deal with PKI's flaws?
There's a Firefox extension, STS UI, that lets you see, add, and edit STS information. Firefox 4 otherwise doesn't provide a way to see what's stored. You can see the preference getting set for various sites (e.g. Paypal) but not mine, despite the correct headers being sent.
[ Parent | Reply to this comment ]
Add the following line:
Header set Strict-Transport-Security max-age:31337
[ Parent | Reply to this comment ]
This Internet-Draft will expire on January 12, 2011.That was a month ago, so it would be unfortunate if the idea was only just starting to take off. Now what?
[ Parent | Reply to this comment ]
[ Send Message | View dkg's Scratchpad | View Weblogs ]
[ Parent | Reply to this comment ]
[ Send Message | View dkg's Scratchpad | View Weblogs ]
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]