views:

702

answers:

2

I use a ASP.Net login control in a straightforward manor however I have spotted that the ASPXAUTH cookie has an expiry date of {01/01/0001 00:00:00}. Should this not get to something to prevent hacker manipulation? I am not issuing the cookie myself I am letting .Net create it.

I have run a scan on my web app and it is able to store the ASPX cookie information, go to the log out page and then go to a page without a need to login I assume using the stored cookie information.

Using the application manually I am unable to do this, it always sends me to the login page when trying to access the page.

The logout page calls FormsAuthentication.SignOut()

EDIT: Turns out this is a known problem! Who knew! http://support.microsoft.com/kb/900111

+1  A: 

You cannot read the cookies expiration date and time. The browser uses the cookies expiration date to determine whether or not to send the cookie to the server. If a cookie has expired, the browser does not send that cookie to the server with the page request, the cookie is deleted.

If the cookie has not expired the cookie is sent to the sever sans expiration information, since this information is utilized by the browser to determine if the cookie should be sent or not. You can read the expiration date from the request, but as you have discovered it returns a date time value of zero.

Try checking the expiry date of Response.Cookies collection in the LoggedIn event. This should yield the correct expiry date of the cookie.

protected void Login1_LoggedIn(object sender, System.EventArgs e)
{
    HttpCookie cookie = Response.Cookies(".ASPXAUTH");
    DateTime expires = cookie.Expires;
}

See Basics of Cookies in ASP.NET for more information.

Phaedrus
Ok I think I understand however reading the Response.Cookie the expiry date is also zero in the LoggedIn event
Jon
Zhaph - Ben Duguid is correct, the reason the expiry date is 01/01/0001 00:00:00 is because you are issuing a non-persistent cookie. Try setting the 'RememberMeSet' property of the Login control to true and then checking the expiry in the LoggedIn event. Remember, as stated by Zhaph, there are security risks associated with setting a persistent authentication cookie on a user’s browser.
Phaedrus
A: 

If you save the value of the cookie, log out, and then re-present that cookie to the server, it will just log you in automatically as if you had never logged out.

This is because you can also tell the .NET framework to set a persistent authentication cookie (by default you can present this option to the user with the "Remember Me?" checkbox exposed with the DisplayRememberMe property of the Login control) so the expiry date would be a value in the future.

When the user comes back to the site and their browser sends the cookie, they are automatically logged in - so the behaviour you're seeing is be design.

If you need to be more secure, the easiest thing to do is add a method to the OnLoggedIn event of the login control, and set a session value (i.e. Session.Add("HasLoggedIn", true)) that you can then check elsewhere, and if it's not true, redirect to the login page:

if (null == Session["HasLoggedIn"] || !(bool)Session["HasLoggedIn"]) {
  FormsAuthentication.RedirectToLoginPage();
}


Edit to respond to comment:

Which is why you're seeing the expiry date of 01/01/0001 00:00:00 - this will be deleted at the end of your session - or when you close the browser - but there's nothing fundamentally wrong with what you're seeing - just because you're not setting a persistent cookie doesn't mean that if you send a copy of an old cookie back to the server it won't log you in with it.

As I said, if you want to ensure that users have to log in each time (or to "resolve" this issue), add a session variable that you set when the user actually logs in, and reject all requests without it.


Further edit for second comment

From Explained: Forms Authentication:

Each time a subsequent request is received after authentication, the FormsAuthenticationModule class retrieves the authentication ticket from the authentication cookie, decrypts it, computes the hash value, and compares the MAC value to help ensure that the cookie has not been tampered with. Finally, the expiration time contained inside of the forms authentication ticket is verified.

Note ASP.NET does not depend on the expiration date of the cookie because this date could be easily forged.

So the cookie has to sent back to the server before the ticket has expired.

Zhaph - Ben Duguid
DisplayRememberMe is false so no persistent cookie exists
Jon
But surely SignOut should remove the cookie so you can't relogin? Isn't this a massive security hole with FormsAuthentication - i.e. just copying a cookie value and even though you're logged out you can just send the cookie value back and it will log you in?
Jon
Thanks for the info but if you see my edit, this also answers part of my question i.e. FormsAuthentication can be bypassed if you copy the cookie value once authenticated and then even if SignOut is called you can still use protected pages
Jon
Yes, which is why I recommend using a session based key on top of that - which would help. Alternatively, you could extend the AspNet_Membership table to include a `LastLogoutDate` and populate that using the OnLoggedOut event - although you'll still have to deal with session timeouts, if you're using InProc session states, you could hook into the SessionEnd event - you could then compare to ensure that the LastLogoutDate was earlier than the built in LastLoginDate.
Zhaph - Ben Duguid
I changed your logic to if ((Session["UserLoggedIn"] == null) || (bool.Parse(Session["UserLoggedIn"].ToString()) == false))
Jon
Good catch! Updated.
Zhaph - Ben Duguid