4

I'm writing a web app that already uses TLS encrypted connections (HTTPS), Secure; HttpOnly session cookie, HMAC-SHA1 CSRF token, requires correct Referer header to avoid Login CSRF and changes session id during login to avoid basic session fixation attacks.

However, I cannot use HSTS because the same domain needs to serve some HTTP content for historical reasons.

I'm failing to understand how to avoid MitM attack that accomplishes session fixation in practice:

  1. Attacker navigates to https://example.com/login and receives a new anonymous session-id cookie and corresponding HMAC-SHA1 csrf-token embedded in login form.
  2. Attacker completes login and the server overwrites the session-id cookie for the new user id.
  3. Attacker saves the value of session-id cookie.
  4. Victim navigates to example.com using HTTP and the attacker initiates MitM attack that modifies the response to have Set-Cookie: session-id=<value-from-attacker-session> and Location: https://example.com/whatever.
  5. Victim's browser now completes full TLS handshake with example.com and does GET /whatever with Cookie: session-id=<value-from-attacker-session>. In practice, this is a completion of session fixation attack because Victim is now running the session shared with the Attacker.

Granted, this is not an easy attack because it requires active MitM attack and the Victim needs to use initial HTTP connection to example.com. In addition, this only allows for session fixation, not session hijacking.

  1. Is HSTS the only way to avoid this attack?
  2. Is there any way to avoid cookies set via HTTP connection being visible on HTTPS connection looking identical to Secure; HttpOnly cookies?

Update 2014-09-04

I'm assuming following claims are true:

  1. TLS connection is secure and the UA has a sane list of trusted CAs.
  2. End user is able to avoid sslstrip-like attacks where browser chrome contains incorrect URL.
  3. example.com is not on the preloaded HSTS list.

The guard cookie suggested by Steffen Ullrich would fix the issue except for the fact that it cannot detect if attack is done during initial connection. Implementing guard cookie would still avoid attack switching the session on-the-fly. Currently MitM Attacker could overwrite the original Secure; HttpOnly cookie called session-id with a regular HTTP cookie any time in the future he can get the UA to access any HTTP URL for the same domain. (This can be pretty easy because the Attacker can redirect any HTTP connection from the same browser session.)

I'm still failing to see any way to really fix this without any assistance from UA. If UAs only had a way to tell which cookies have been set over TLS connection instead of plain old HTTP...

(As a side not I have to say that all the suggestions to detect sslstrip-like attacks by server side like described in the answer linked by Steffern Ullrich seem vain because all suggestions require sending JavaScript files that do the detection and sslstrip is strictly about MitM attacker able to modify files on the fly. As such, the Attacker can easily make any JavaScript detection to always return "ok".)

Related links: 1. Cookie forcing 2. Login CSRF

  • Can't you redirect the historical http links to HTTPS? I've answered similar questions to this before regarding mitm and login csrf. Search my history (sorry I'm not at a computer atm for direct link) . – SilverlightFox Sep 03 '14 at 10:01
  • 1
    @SilverlightFox the problem is an attacker can still set the cookie before the user is redirected. Even if HSTS is enabled an attacker could strip the header the first time the user visits. – thexacre Sep 03 '14 at 10:23
  • @the I understood the question. My previous answers to other questions cover some points. Eg, 2) no, the cookies appear identical to the server regardless of specific flags. – SilverlightFox Sep 03 '14 at 10:33
  • 2
    HSTS is a good way to avoid the problem but you need your site to be in the preloaded list. You cannot completely avoid this problem without it (ie. Internet Explorer users would be vulnerable) – SilverlightFox Sep 03 '14 at 10:37
  • 1
    What you are describing is [SSL-strip](http://www.thoughtcrime.org/software/sslstrip/). The problem is, that the server cannot detect whether the page was requested by the user or by a MITM. Even if there would be something like safe cookies, the MITM could transform them to normal cookies easily. – martinstoeckli Sep 03 '14 at 11:01
  • I cannot redirect historical HTTP links to HTTPS because the historical HTTP content contains embedded IFRAMEs from domains that do not support HTTPS. Unfortunately, allowing mixed content cannot be decided by the server. – Mikko Rantalainen Sep 04 '14 at 08:33
  • The problem was solved by using HSTS with preload lists. Old historical content was finally deemed old enough to be allowed to rot away. – Mikko Rantalainen Mar 12 '21 at 13:14

3 Answers3

3

How to avoid session fixation (Login CSRF) by MitM attack without HSTS?

You can't. You need to have your site in the HSTS preloaded lists to avoid this type of MITM attack otherwise the attacker could MITM the first connection and set the session cookies to fixate it to the attacker's session.

However, I cannot use HSTS because the same domain needs to serve some HTTP content for historical reasons. ...the historical HTTP content contains embedded IFRAMEs from domains that do not support HTTPS

This should not stop you from setting an HSTS policy.

For example, host your historical content on legacy.example.net. Note that this needs to be a different domain from your secure content (www.example.com), not a subdomain for submission onto Chrome's Preloaded list as the includeSubDomains flag needs to be set on the header. If your historical page was http://www.example.com/iframe.htm replace this with a redirect to http://legacy.example.net/iframe.htm. This will allow you to serve the historical HTTP content and embed an iFrame to a HTTP domain without any browser security warnings.

So a user navigating to some historical content with HSTS preloaded will get the following process.

  1. User enters the normal URL for the content in their browser's address bar: http://www.example.com/iframe.htm.
  2. Browser checks its own HSTS preloaded list and finds www.example.com.
  3. Browser upgrades the connection to TLS by changing the URL to https://www.example.com/iframe.htm
  4. Server receives request and issues a 301 redirect to http://legacy.example.net/iframe.htm
  5. Server at legacy.example.net displays IFrame containing 3rd party HTTP content, and everybody is happy.

This will allow you to use HSTS for your application while allowing historical IFrame hosting content to function without issue. Also, you might find my other answer on protecting against login CSRF useful, as it also covers MITM attacks.

SilverlightFox
  • 33,408
  • 6
  • 67
  • 178
  • 1
    According to https://hstspreload.appspot.com/ , you need to have the `includeSubdomains` token,so all subdomains must also be HTTPS. That means you need another domain just for that. – Kobi Sep 05 '14 at 11:47
  • 1
    @Kobi: Thanks, answer updated to take this into account. – SilverlightFox Sep 05 '14 at 12:07
2

Interesting question. What your are describing is an environment, where the attacker mounts a man-in-the-middle attack, where it can read and modify the users HTTP traffic but not HTTPS traffic. This excludes SSLStrip-like attacks and SSL man-the-middle so you might look here for ideas on how to detect these kind of attacks at the server.

In the environment you describe the following assumptions should be valid:

  • The attacker cannot read the original session cookie or any other cookies which have the Secure and HttpOnly flags set. Moreover, it cannot even see which cookies are in use inside a HTTPS connection.
  • But it can read, modify and create cookies within insecure HTTP. This will also allow the attacker to create or modify cookies which have the Secure flag, even if he cannot read them.

Based on this the following might work:

  • Server sends a session cookie with value session-id with Secure and HttpOnly flags.
  • Server sends also a "guard" cookie with a name somehow based on the session-id and the value "GuardCookie", also with Secure and HttpOnly flag and with the same life time as the session cookie.
  • Whenever the server updates the session cookie it makes the guard cookie reflect the new session, that is if the name of the guard cookie needs to be changed the old guard cookie must be invalidated and a new one set. Or a user specific name of the guard cookie could be chosen randomly at login and included hashed inside the session-id.

The attacker can override the session cookie with its own and it can also add the guard cookie from its own session. But, it can not remove the guard cookie from the users session because it does not know its name. Therefore if the server receives a request from the client over HTTPS it has to check:

  1. Is a valid session-id included. If not the session gets reset.
  2. Is the guard cookie derived from the session-id included? If not the session gets reset.
  3. Are there any more cookies with the value "GuardCookie"? If yes the session gets reset and all existing guard cookies get removed.

With the last step the server can detect the session fixation attack, because the attacker is not able to remove the guard cookie for the original session.

I'm not completely sure if this will work, but it sounds like an approach worth a discussion :)

Edit: like user SilverlightFox noticed, the attacker can still fixate a fresh user without previous session to the attackers session. This idea helps only in detecting the replacement of an existing session.

Steffen Ullrich
  • 184,332
  • 29
  • 363
  • 424
  • 1
    Interesting answer. This has the same problem as HSTS when not preloaded... The first attack would be undetectable and also this would be undetectable if there was no current user session too. – SilverlightFox Sep 03 '14 at 21:29
  • 1
    The assumption was, that SSL Man-In-The-Middle (replacing the certificate) is not possible, which is IMHO a valid assumption because this kind of attack is detectable by the user (browser complains). And as for detecting SSLStrip see the link I've provided in the answer. Based on this I don't see your problem, because the attacker does not know the guard cookie for the users session and thus cannot delete it. And yes, the attack only cares about the case where there is a user session, because that is the one you need to protect most. – Steffen Ullrich Sep 04 '14 at 04:38
  • 1
    Yes, the session fixation is undetectable this way for a fresh user without a session. Good point. – Steffen Ullrich Sep 04 '14 at 04:43
  • I just noticed that attacker can avoid the guard cookie because all commonly used browsers limit max cookies per domain with FIFO storage. The attacker can just set cookies `discard000=1` ... `discard100=1` to drop all other cookies for a given domain. As a result, step 3 in the above algorithm will not ever see extra guardcookies. – Mikko Rantalainen Jun 16 '21 at 10:25
1

On modern browsers, you can (and probably should) use the __Host- prefix in you cookie name. On moderns browsers, these cookies can only be set from a secure origin and cannot use the Domain attribute (and thus cannot be be set from a subdomain).

If your origin is https://www.example.com, they can be set from:

but they cannot be set from:

Note that this may not be supported before Safari 14.

References:

ysdx
  • 851
  • 6
  • 14
  • 1
    Good point. Attacker cannot set cookie with prefix `__Host-` without abilitity to break TLS and cannot therefore *overwrite* the secure cookie which is the attack vector in the question. Unfortunately, older iPads that still work are not able to run Safari 13. To support those devices, HSTS preload is the only option - obviously it's *now* too late to apply to the list because those devices are no longer updated. Those old devices will still work with the `__Host-` prefix but those will not get the protection provided by the prefix. Obviously, those old devices are already vulnerable. – Mikko Rantalainen Mar 12 '21 at 13:28
  • I changed this answer to be the "accepted" one because I nowadays think that using `__Host-` prefix is the only secure way to actually protect against this attack. That special cookie prefix obviously cannot help older iPads or other Apple devices without up to date software but those will have multiple security vulnerabitilities in any case and there's no way to protect those devices from this attack. It's also possible to use prefix `__Secure-` if you really need that but I would recommend using `__Host-` for nearly all cases instead. – Mikko Rantalainen Feb 23 '22 at 14:44