使旧会话Cookie无效-ASP.网络标识



一家外部公司对ASP进行了一些渗透测试。NET MVC 5应用程序。

他们提出的一个问题描述如下

与会话管理链接的cookie称为AspNet。ApplicationCookie。手动输入时,应用程序将对用户进行身份验证。即使用户从应用程序注销,cookie仍然有效。这意味着,旧的会话cookie可以在不受限制的时间范围内用于有效的身份验证。在插入旧值的那一刻,应用程序接受它并用新生成的cookie替换它。因此,如果攻击者获得了对其中一个现有cookie的访问权限,则会创建与过去相同的有效会话。

我们使用的是ASP。NEt Identity 2.2

这是我们在账户控制器上的注销操作

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

在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())))
            }
        });

我本以为该框架会处理使旧会话cookie无效的问题,但会浏览Owin。安全源代码似乎不是。

如何在注销时使会话cookie无效?

编辑杰米·邓斯坦的建议我添加了AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);,但没有什么不同。我仍然可以注销应用程序,在Fiddler中克隆以前经过身份验证的请求,并让应用程序接受它。

编辑:我更新的注销方法

 [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");
    }

确保按照Jamie的建议正确使用AuthenticationManager.Signout(DefaultAuthenticationTypes.ApplicationCookie);

能够再次使用相同的cookie登录是经过设计的。Identity不会创建内部会话来跟踪所有登录的用户,如果OWIN获得了符合所有框的cookie(即上一个会话的副本),它将允许您登录。

如果在安全戳更新后仍然可以登录,那么OWIN很可能无法获得ApplicationUserManager。确保这条线刚好在app.UseCookieAuthentication 上方

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

或者,如果您正在使用DI,请从DI:中获取ApplicationUserManager

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

还要将validateInterval: TimeSpan.FromMinutes(30)降低到更低的值——我通常会稳定几分钟。这就是Identity将authcookie中的值与数据库中的值进行比较的频率。比较完成后,Identity会重新生成cookie以更新时间戳。

Trailmax的答案很准确,我想我应该补充一点,如果有人在使用ASP的同时尝试这样做。NET Boilerplate,下面是我用来做这件事的:

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

我最初有:

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

并且is不起作用。

你走在了正确的道路上。事实上,最简单的方法是更新用户SecurityStamp,但是通常执行它不会成功,因为实际上凭据没有更改,并且在数据库中保持不变。解决方案,试试这个:

private string NewSecurityStamp()
        {
            return Guid.NewGuid().ToString();
        }
private async Task RegenerateSecurityStamp(string userId)
    {
        var user = await _userManager.FindByIdAsync(userId);
            if (user != null)
            {
                user.SecurityStamp = NewSecurityStamp();
                await _userStore.UpdateAsync(user);
            }
    }
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> LogOff()
    {
        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
        await RegenerateSecurityStamp(User.Identity.GetUserId());
        return RedirectToAction("Login", "Account");
    }

最新更新