7

I am being asked about cookie replay attacks with my ASP.NET websites forms authentication.

I have followed the advice below to protect against any attack but think that the site is still vulnerable if somebody manages to get at the cookie (albeit only for a short time). Is there a way to completely destroy the forms authentication session on logout so that even if someone had stolen the cookie there would be no chance of using it maliciously

Advice followed was

We believe we have taken all responsible steps we can to protect against this within the confines of ASP.NET. Please see detailed response below.

However we have implemented the recommended steps from Microsoft to defend against this (see http://support.microsoft.com/default.aspx?scid=kb;en-us;900111)

· The authentication cookie is never written to a client machine making it hard to steal.

· The application is run-able via SSL so a cookie is never issued over a non secure connection

· We enforce absolute expiration with a 15 minute timeout meaning that any issues cookie is useless after that time limit

· We use httpOnly cookies so that no-one can pro grammatically intercept or alter this cookie.

So even if the above precautions were broken, which we think highly unlikely, a malicious user would only have 15 minute window to break the precautions and successfully log in

AJM
  • 32,054
  • 48
  • 155
  • 243

4 Answers4

5

A simple idea is to generate a random guid and store it in the user data section of the cookie. Then, when a user logs out, you retrieve the guid from the user data and write it in a server side repository with an annotation that this "session" has ended.

Then, have an http module that checks upon every request whether or not the guid from the userdata section of your cookie doesn't point to a ended session. If yes, terminate the request with a warning that expired cookie is reused.

This comes with a cost of an additional lookup per request.

Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
  • 6
    An additional cost is that this approach does not scale well, because in a heavily-used web app you will soon have a huge table full of GUIDs. Wouldn't it be better to store the GUID of the current session in the user row in the database and set it to NULL when the user logs out? This way, you'll have a maximum of GUIDs to store. – thomaskonrad Jul 08 '15 at 13:57
  • 1
    @to0om: this could lead to suble issues when the same user has multiple active independent sessions (e.g. in different browsers) and terminates some of them without terminating others. – Wiktor Zychla Jul 08 '15 at 15:28
  • 1
    That's right. If one wants to support multiple concurrent sessions, then a separate session GUID table with a one-to-many relationship could solve the problem. I just don't like the idea of storing expired GUIDs, because if you take this seriously, you have to store them forever in order not to re-enable old sessions later. Storing active GUIDs, maybe combined with a plausible limit of 10 concurrent sessions, limits the maximum number of GUIDs one would have to store. – thomaskonrad Jul 09 '15 at 07:56
  • 2
    @to0om: a possible workaround would be to just store guids for limited period of time, I don't think you need an unlimited history. – Wiktor Zychla Jul 09 '15 at 11:28
  • @WiktorZychla I would err on the side of caution if a user explicitly clicks the "Log out" button - destroy all sessions server side for the identity. If the user wants to maintain two sessions on different user agents, or different machines, they're probably not going to be clicking "Log out". Conversely, you wouldn't want to assume that when the user *did* click "Log out" that they meant "just this session, not the others" - high risk assumption IMO. Terminate all of them and save the server-side session tracking complexity. – Matt Kocaj Oct 28 '17 at 08:27
  • @MattKocaj: *Conversely, you wouldn't want to assume that when the user did click "Log out" that they meant "just this session, not the others* This is how most big sites works. You click logout on one device but remain logged in everywhere else. – Wiktor Zychla Oct 28 '17 at 13:37
  • @WiktorZychla I see your point. My issue is that many of those sites would be venerable to a cookie replay attack precisely because the "session" is not tracked server side, but simply by the client having said cookie. If a user is going to go to the trouble of clicking "Log out" and I was trying to address this `Cookie replay attack - protection` issue, then I'd trade the UX for security and destroy all sessions. IMO complexity is a cost which impacts security so I'd choose the simpler logic, destruction of *all sessions* and proper cookie replay protection. But that's just me. – Matt Kocaj Oct 31 '17 at 02:37
3

Is there a way to completely destroy the forms authentication session on logout so that even if someone had stolen the cookie there would be no chance of using it maliciously

The way is to keep track on your server that the user is logged out and what time, so even if its going to see a page using a valid authenticated cookie, you double check if this user is also logged on your server records or not.

This means that you must have an extra table on your database to keep and check the login logout of your users status and not been 100% count on the authentication cookie.

Is there a way to completely destroy the forms authentication session on logout

In the worst scenario that the cookie is stolen, you actually can't.

Why is that, because the form authentication is actually keep on the cookie all the data (like when is expired, who user is, etc). So you can not delete that, is on the cookie, and the alternative is to synchronize that with your custom data on the server and have an extra level of security.

Related: Can some hacker steal the cookie from a user and login with that name on a web site?

Community
  • 1
  • 1
Aristos
  • 66,005
  • 16
  • 114
  • 150
  • The user data section of the cookie can be used to store an additional information you could use to correlate forms cookies with server-side persisted information. Thus, you actually CAN detect whether or not a cookie is reused after the session has been ended. – Wiktor Zychla Apr 17 '13 at 16:03
  • @WiktorZychla But if the hacker get and replace both the session cookie with the logged in cookie ? Then is by pass your check. – Aristos Apr 17 '13 at 17:09
  • There is a single, encrypted forms cookie, with guid in session data. This guid corresponds not to server side session but is just an additional unique guarding token. – Wiktor Zychla Apr 17 '13 at 17:56
1

You can easily invalidate forms auth tickets that are "older than date X".

A FormsAuthenticationTicket has a built-in property called IssueDate that allows you to do that.

You can, for example, do this:

  1. store a date in user's database record, you can name it ValidSince
  2. read the token date inside Application_AcquireRequestState (in global.asax)
  3. if the token's IssueDate is older than the database date - logout!

When you want to invalidate a particular user - just reset that date in the database to the current date.

I blogged about it here if you need some actual code samples.

One very common use case is to "invalidate all sessions created before the last password-change".

Alex from Jitbit
  • 53,710
  • 19
  • 160
  • 149
0

I implemented a system that stores the SessionID in the auth cookie on the first authenticated request and then verifies the active SessionID matches the cookie on subsequent requests. Details on this answer. This avoided the server side tracking suggested in @WiktorZychla's answer.

This could probably be improved by storing a hash of Incoming IP + Request.Browser + SessionID in the session and the auth cookie, rather than just the SessionID.

foldinglettuce
  • 522
  • 10
  • 28