3

ASP.NET documentation says:

FormsAuthentication.SignOut()

Removes the forms-authentication ticket from the browser

Why is the cookie not invalidated at the server as well? It would be easy to implement. After all this code runs at the server. In fact it's easier to implement on the server because the server trusts itself, whereas clearing the cookies on the client requires cooperation by the client. What if the client fails to cooperate by error or maliciously? What then?

I tested this code and it does what it says. It removes the cookie on the browser, and it leaves the server side cookie valid. I took a copy of the cookie prior to signing out, and then signed myself back in with that cookie without providing username and password.

So what's the worse that could happen? This:

  1. Bob is logged in and saves his session cookie to notepad
  2. Administrator wants to revoke Bob's access immediately and sets a flag that triggers FormsAuthentication.SignOut() on the next web request from Bob. The administrator also changes Bob's password.
  3. Bob's browser reacts to SignOut() by clearing his cookie and he is signed out imediatelly. Bob sees a message "you have been signed out", he tries to hit the back button but he is really signed out. He can't get back in. He tries logging in with his username and password, but it says his password is invalid.
  4. Administrator watches server logs and sees that SignOut() was executed successfully.
  5. Bob uses saved session cookie to log back in (and is allowed). He continues working on the system indefinitely.

Isn't this a bad thing? Is this just ASP.NET or do other frameworks do it this way?

Rory Alsop
  • 61,367
  • 12
  • 115
  • 320
user3280964
  • 1,130
  • 2
  • 7
  • 13

3 Answers3

3

First, let's clear up a misconception. There is no such thing as a "server-side cookie." While a server can send cookies with an HTTP response, there is no server-side cache of valid cookies. That is a construct that only exists on the client side in a user agent (such as a browser) that supports it. This is what makes cookies powerful. You can maintain state for thousands, or hundreds of thousands of users (or more!) and the only resources required are a little bit of memory and storage on each client machine, and none at all on the server side. The only knowledge a server needs to have of a cookie is how to parse it out of a request, and how to set it (if required) on a response.

Now, let's talk about Forms Authentication specifically. Forms Auth is a purely cookie-based authentication mechanism. (For the sake of simplicity and to focus on the question at hand, I'm going to leave cookieless-FormsAuth out.) This means that you have a simple, light-weight, easy to configure authentication mechanism that requires little in the way of server resources and no shared server-side state management process and overhead.

What this also means, is that when you send that original authentication ticket to the client, for as long at that ticket is valid, it can be used to authenticate future requests. No change that you make (expiring the cookie, setting additional expiration information in a new ticket and replacing the cookie, adding additional "logged out" cookies" can prevent the original cookie from being used as long as it is valid.

Is this a problem? In practice, not usually. For most applications, this does not create a specific threat that needs to be mitigated and the ability to authenticated users without being tied to a server-side resource investment requirement is quite attractive. If you can't quantify the value of adding the additional mitigation of server-side session invalidation for your application, then implementing it is a net loss, not a desirable outcome.

If the threat model for you application does demonstrate a specific reason to need to securely de-authenticate sessions, then bare Forms Authentication is not for you, and you need to implement a server-side session validation mechanism on top of it track authentication state to determine which users are valid authenticated users and drop requests from all others, regardless of the nominal validity of the authentication ticket submitted with a forms auth cookie.

Lastly, do other frameworks work this way? Certainly many do. This is a necessary property of any stateless authentication system that is relying on a ticket submitted by a client to determine authentication state, and that's probably more authentication mechanisms than not. Authentication systems that have a server-side session management component can avoid this by tracking authentication state server-side, whether any given system does it correctly is up to the reader to test. Not as germane but worth mentioning...Not all authentication systems have the concept of signing out in the first place. If you're using certificate authentication, or integrated authentication, for instance, there is really no concept of "signing out" and transition back from an authenticated to an unauthenticated state, and in these cases the issue is irrelevent.

Xander
  • 35,525
  • 27
  • 113
  • 141
  • I think I finally get it. So since there is nothing stored at the server, it means that the cookie contains username and ticket expiration time in encrypted form. Is there anything else that the cookie contains that I'm forgetting about? – user3280964 May 27 '19 at 21:49
  • @user3280964 Exactly. There are a couple of other properties that don't add much, (Expired, IsPersistant, IssueDate, etc.) but there is a UserData property that can be interesting because you can add application specific data there. One other thing worth mentioning is that if you don't enable sliding expiration, there is a finite lifetime for the ticket to be used, and even without any server-side component, once that time has passed, it will become invalid and useless to a malicious actor. – Xander May 27 '19 at 21:54
  • Is the encryption key used for encryption machineKey from web.config? Or is there some other key that encrypts this? – user3280964 May 27 '19 at 22:09
  • @user3280964 Yes, that's the one. If there isn't one is web.config, one will be generated for the application based on the configuration specified by the Machine.config. – Xander May 27 '19 at 23:29
1

Can this be exploited?

Yes, the attack is exactly as you described it. An attacker who could steal a token is valid, even after the user logs out. This is not best practice, although how practical this is is up for debate.

Why does ASP.NET do this?

This is a difficult thing to answer, as we don't know the design mentality behind it. What is clear that it is a security flaw, and that one should never rely on client-behavior.

How can this be worked around?

Essentially, after the client cookies have been cleared, the cookie needs to be invalidated. This question on Stack Overflow deals with the exact same problem, and offers a wide variety of solutions for it.

Do other frameworks do this?

I can't say for sure. It would make sense to check the documentation. As a general rule-of-thumb, depending on any client-side behavior (aside from any defense-in-depth measures) for security should be considered a crimson-red flag!

0

Looks like this is a known session replay vulnerability in ASP.NET with several workarounds .

user3280964
  • 1,130
  • 2
  • 7
  • 13