I have an application that requires a username and password. When a user clicks on the log out button, it runs:
private void LogOut()
{
Session["SessionName"] = null;
Session.Remove("SessionName");
System.Web.Security.FormsAuthentication.SignOut();
Response.Cookies.Remove("AuthCookie");
HttpCookie c = new HttpCookie("AuthCookie");
c.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(c);
Session.Clear();
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetExpires(DateTime.Now.AddDays(-1));
Response.Cache.SetNoStore();
Response.Cache.SetNoServerCaching();
Session.Abandon();
Response.Redirect("~/user/login.aspx");
}
The problem is when I test for security. When I go to a page to change data in the database, I can use Fiddler to 'record' this request. After I log out of the application, I can still replay this request in Fiddler just as if I were still logged in. In fact, I can still see all the cookie and session information when I place breaks in my code. Only after the session expires (from a timeout) does the actual session go away.
How come I can still see this information after I expired the cookie and abandoned the session? How can I completely clear the cookie and session information when the user clicks on the log out button?
According to MSDN (http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.signout.aspx),
Calling the SignOut method only removes the forms authentication cookie. The Web server does not store valid and expired authentication tickets for later comparison. This makes your site vulnerable to a replay attack if a malicious user obtains a valid forms authentication cookie.
They give three ways to mitigate this risk. Only the last method (using persistent storage to keep track of login status yourself) will prevent the actual user from replaying the request. The first method just reduces the window of time of the vulnerability, and the second method keeps cookies secure from 3rd parties.