Invalidate Old Session Cookie - ASP.Net Identity

2019-02-03 03:05发布

问题:

An external company has done some penetration tests on the ASP.NET MVC 5 application i'm working on.

An issue that they raised is described below

A cookie linked with session Management is called AspNet.ApplicationCookie. When entered manually,the application authenticates the user. Even though the user logs out from the Application,the cookie is still valid. This means,the old session cookie can be used for a valid authentication within unlimited timeframe. In the moment the old value is inserted, the application accepts it and replaces it with a newly generated cookie. Therefore, if the attacker gains access to one of the existing cookies, the valid session will be created,with the same access as in the past.

We're using ASP.NEt Identity 2.2

Here's our logout action on the account controller

 [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOff()
    {
        AuthenticationManager.SignOut();
        return RedirectToAction("Login", "Account");
    }

in startup.auth.cs

 app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            ExpireTimeSpan = TimeSpan.FromHours(24.0),
            Provider = new CookieAuthenticationProvider
            {
                // Enables the application to validate the security stamp when the user logs in.
                // This is a security feature which is used when you change a password or add an external login to your account.  
                OnValidateIdentity = SecurityStampValidator
             .OnValidateIdentity<ApplicationUserManager, ApplicationUser, int>(
                 validateInterval: TimeSpan.FromMinutes(1.0),
                 regenerateIdentityCallback: (manager, user) =>
                     user.GenerateUserIdentityAsync(manager),
                 getUserIdCallback: (id) => (Int32.Parse(id.GetUserId())))

            }
        });

I would have thought that the framework would have taken care of invalidating an old session cookie but browsing through the Owin.Security source code it appears not.

How do i invalidate the session cookie on logout?

edit on Jamie Dunstan's Advice i've added AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie); but then has made no difference. I can still still log out of the application, clone a previously authenticated request in Fiddler, and have it accepted by the application.

Edit : My updated Logoff method

 [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> LogOff()
    {
        var user = await UserManager.FindByNameAsync(User.Identity.Name);

        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
        await UserManager.UpdateSecurityStampAsync(user.Id);

        return RedirectToAction("Login", "Account");
    }

回答1:

Make sure you use AuthenticationManager.Signout(DefaultAuthenticationTypes.ApplicationCookie); as correctly suggested by Jamie.

Being able to login with the same cookie again is by design. Identity does not create internal sessions to track all logged-in users and if OWIN gets cookie that hits all the boxes (i.e. copies from the previous session), it'll let you login.

If you still can login after the security stamp is updated, most likely OWIN can't get a hold of ApplicationUserManager. Make sure you have this line just above the app.UseCookieAuthentication

app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

Or if you are using DI take ApplicationUserManager from DI:

app.CreatePerOwinContext(() => DependencyResolver.Current.GetService<ApplicationUserManager>());

Also reduce the validateInterval: TimeSpan.FromMinutes(30) to lower value - I usually settle for couple minutes. This is how often Identity compares values in auth-cookie to the values in the database. And when the comparison is done, Identity regenerates the cookie to update timestamps.



回答2:

Trailmax's answer is spot on, I thought I would add that if someone is trying to do this while also using ASP.NET Boilerplate, the following is what I used to make this work:

app.CreatePerOwinContext(() => IocManager.Instance.Resolve<UserManager>());

I originally had:

app.CreatePerOwinContext(() => IocManager.Instance.ResolveAsDisposable<UserManager>());

and is wasn't working.