26

HTTP Strict Transport Security (HSTS) is a very useful feature at preventing OWASP a9 violations and attacks like SSLStrip which try and prevent the client from making a secure connection. This technology however isn't in older versions of web browsers(most notibly IE). In June 2015 Microsoft finally added support for HTTP Strict Transport Security to IE 11 on Windows 7, 8.1, and 10. Microsoft Edge supports it as well. Both of those will do HSTS pre-load for sites that are on the Chromium pre-load list. However not all users use the latest web browsers.

So how do you protect users with browsers that don't support HSTS? What is the "best" level of transport security that a web application can provide despite serving content to an insecure client?

(Shout out to Tylerl for bringing up this question.)

Robert Mennell
  • 6,968
  • 1
  • 13
  • 38
rook
  • 46,916
  • 10
  • 92
  • 181
  • 2
    Damn, that's a hard one. I'm trying to think of ways to enforce this without browser support, but at the end of the day an attacker can always MitM them. – Polynomial Nov 06 '12 at 16:26

4 Answers4

22

You can't.

The best you can do is to use SSL sitewide. Have all HTTP connections immediately redirect the user over to HTTPS (redirect over to the front page via HTTPS, e.g., http://www.example.com/anything.html should redirect to https://www.example.com/). Don't serve any content over HTTP (other than an immediate redirect to your front page, over HTTPS). Set the secure flag on all cookies (obviously).

This isn't going to stop a man-in-the-middle attack that downgrades the user to HTTP. Without HSTS, you can't prevent that kind of attack.

You just can't do any better than that. Oh well. That's just how it goes with IE.

See also Options when defending against SSLstrip?.

D.W.
  • 98,420
  • 30
  • 267
  • 572
7

Obviously there is no way for you to prevent an attack that would happen before the traffic even arrives at your server. You're just not in a position to have any affect at that point.

However, one thing you can do to prevent non-SSL traffic from ever being sent is to intentionally break non-SSL links. As webmaster will typically test their links at least once before they go live, this will clue them in that they need to change their protocol to https.

A simple way to do this is to instead show a page which warns the user that they arrived via an insecure link and instructs them to "update their bookmarks" etc, and then provides an https link to proceed to where they wanted to go. It's fairly unintrusive and doesn't hinder normal users too much, but it gives the hint to web designers who are the target of this type of campaign anyway.

You probably want to give this page a 404 status code so that it isn't interpreted as real content. The downside is that search engines rely on a 302 redirect to update their index to point to the correct page. Returning a 404 will remove the link from the index instead of updating it to https. So you may want to send bots a 302 and send browsers to your 404 "update your links" page.

tylerl
  • 82,225
  • 25
  • 148
  • 226
  • A much more user friendly approach to this would be to do a perminant redirect on the non SSL URL to the SSL URL. I have done this on several administration sections of my websites before and it works pretty well. It still won't do anything if they send data in their first request that shouldn't have been sent clear, but it forces them over as soon as the server possibly can. – AJ Henderson Nov 06 '12 at 21:53
  • 1
    @AJHenderson That solution is certainly the most common one, but it very specifically doesn't solve the problem that this question is about. – tylerl Nov 07 '12 at 00:14
  • Perhaps I didn't understand your answer then. Assuming you don't have an active attacker accessing the server via HTTPS and then relaying the content to the client via an unsecure means, then HTTPS on all the time would work. If they are accessing it via HTTPS and sending the client HTTP, then I don't see how giving a 404 would help since the server would think it was sending a secure connection. – AJ Henderson Nov 07 '12 at 14:26
  • Hmm, that does give another idea though. I don't understand the exact mechanisms of SSLStrip, but is it able to preserve an HTTPS session with the server? If not, you could use that to provide a token to the client via the initial connection and only continue to send that token during that session. If the token value changes, you would know an attack was being carried out. – AJ Henderson Nov 07 '12 at 14:28
  • Never mind, looks like that doesn't work against SSLStrip since it prevents a secure connection from ever forming. The token would be sent to the attacker and could be relayed. – AJ Henderson Nov 07 '12 at 14:45
  • [HSTS preload](https://hstspreload.appspot.com/) fixes the vulnerability window on first access. Also, with HSTS, user agents will [rewrite the url](https://tools.ietf.org/html/rfc6797#section-8.3) and not show the http warning you suggest. – Tobu May 09 '15 at 19:15
6

HSTS is the only protection against SSLStrip, however you can take the following precautions to help prevent attack:

  1. Make sure your web application is free of Mixed Content vulnerabilities. This really goes beyond HSTS because doesn't protect against pulling JavaScript over HTTP from other domains.

  2. A common solution to security problems is EDUCATION. Provide a unobtrusive message to users that they are using an insecure browser and that they should consider using Chrome or Firefox.

  3. Set the "secure" flag on http cookies (but everyone should be doing this anyway and it doesn't stop SSLStrip).

  4. Introduce JavaScript on each page that detects if the page has been loaded over HTTP (Which should be impossible because of HSTS), and prevent the user from using your web application. Display a huge RED window saying YOU ARE UNDER ATTACK. This could be removed with a targeted MITM attack, but not if the attacker is just blindly using SSLStrip.

Michael
  • 2,391
  • 2
  • 19
  • 36
rook
  • 46,916
  • 10
  • 92
  • 181
3

The first thing that comes to mind is setting the server to only accept SSL connections on the relevant pages and not allow HTTP connections. This should defeat the server sending anything sensitive back to the user in the clear, but ultimately isn't going to stop an active MITM that can make an insecure connection to the user but then convert it to an SSL connection from the attacker to the server.

Ultimately I'm not sure if there is a whole lot more that can be done than that though since without a mechanism to inform the client that they shouldn't send stuff in the clear, they are going to accept whatever they are told.

This brings up another point, I don't know a whole lot about HSTS but it seems like an active attacker that can prevent direct communication between the host and client could also simply strip the HSTS since HTTPS isn't normally used with a client certificate. The user would not see a secure connection to begin with, but if we aren't trusting the user to know what should or shouldn't be HTTPS, then really, it probably wouldn't be much of a stretch for anything we could add checking for HTTPS to be stripped as well.

I suppose another idea would be to put some kind of a JavaScript call that would check the connection type and display a warning, but again, this could potentially be stripped by an active attacker. https://stackoverflow.com/questions/414809/how-do-i-determine-whether-a-page-is-secure-via-javascript

AJ Henderson
  • 41,816
  • 5
  • 63
  • 110
  • 3
    *"it seems like an active attacker that can prevent direct communication between the host and client could also simply strip the HSTS"* - You need to understand the threat model for which HSTS helps. The idea is, if the first connection to the site is not MITM'ed, then the browser sees and remembers the HSTS data, and can't be MITM'ed on subsequent connections. (This is reminiscent of SSH's protections.) Also, Chrome and Firefox will preload HSTS information for a whole bunch of sites (it's hardcoded in the browser), so for those sites you're protected even on your first visit. – D.W. Nov 06 '12 at 17:27
  • Yeah, sorry if I wasn't clear. I was simply expressing that if the user isn't going to take some responsibility for checking that their connection is secure, HSTS doesn't provide much assistance, atleast with an active attacker. I was just talking about it in relation to seeing what is lost between what HSTS provides and what I was discussing. I didn't mean to indicate that I felt that was a goal of HSTS. – AJ Henderson Nov 06 '12 at 21:41
  • *"if the user isn't going to take some responsibility for checking that their connection is secure, HSTS doesn't provide much assistance"* - This is not quite right. As long as the user has connected securely at some point in the past, HSTS protects their future connections (until it expires). Think of a user who connects via a number of different networks, only one of which has a MITM attacker. P.S. Also, I find language like "take some responsibility" to be a bit too focused on blame. If you want to protect users, you have to set aside blame and focus on what actually works for people. – D.W. Nov 07 '12 at 05:21
  • Your last point about the JavaScript message is interesting. Of course it can be stripped away, but it would prevent attacks from automated tools. You could improve it by checking HTTPS **and** comparing the domain, so if an attacker offers SSL from his own domain, it would give a warning too. – martinstoeckli Nov 07 '12 at 10:50
  • @martinstoeckli yeah, and various obfuscation techniques could be used to try to masquerade the code so that it couldn't be easily stripped, such as have code that calls it and fails if it isn't present for example. – AJ Henderson Nov 07 '12 at 14:17