【问题标题】:Security loophole around password changes with .NET FormsAuthentication and persistent cookies?使用 .NET FormsAuthentication 和持久性 cookie 更改密码的安全漏洞?
【发布时间】:2012-04-14 04:51:18
【问题描述】:

好的,这是一个场景:

  1. Bob 登录 mysite.com,它使用 .NET 表单身份验证,并勾选“记住我”。
  2. 夏娃偷了鲍勃的笔记本电脑
  3. Bob 得到了一台新笔记本电脑,并更改了密码。

现在,Eve 有一台被盗的笔记本电脑,上面存储了一个持久性 cookie,这将使她以 Bob 的身份登录 mysite.com - 据我所知,这将起作用 即使 Bob 更改了密码

默认情况下,表单身份验证 cookie 不包含 Bob 的密码(无论是明文、散列还是其他加密) - 所以 Bob 的密码根本不参与 cookie 身份验证过程,并且与上周使用的用户名相同今天仍然可以工作。

这是一个很容易解决的漏洞 - 只需设置 FormsAuthentication.SetAuthCookie("username:passwordHash") 或其他东西,然后在您的身份验证处理程序中解密和拆分 cookie - 但我很难相信这个问题存在于盒子'...我错过了什么吗?

编辑:请注意,我在这里假设“记住我”按钮的目的是避免您每次访问网站时都必须输入密码。这适用于 Facebook、Twitter、Gmail 以及我能想到的几乎所有其他网站 - 如果这不是 .NET FormsAuthentication 中“持久 cookie”选项的目的,我会感到非常惊讶。

另外,是的,我接受对每个传入请求执行双因素身份验证会产生一定的开销,但实际上它只比根据用户从数据库中检索用户的成本略高用户名,无论如何您可能都会这样做。

编辑 2:似乎至少有一个主要的 .NET 站点 - CodePlex.com - 易受此攻击;见http://codeplex.codeplex.com/discussions/350646

【问题讨论】:

  • 您不应该将 cookie 中的数据与数据库中的数据进行比较吗?
  • 是的 - 但是 FormsAuthentication cookie 只包含用户名,并且用户名不受密码更改的影响...
  • 当用户更改密码时,只需删除cookie即可。
  • 在我看来你是对的。我刚刚在 .NET 网站上更改了密码,即使在重新启动浏览器以清除会话后,我仍然可以从另一台计算机访问该网站(作为登录用户)。看来永久 cookie 确实比您想象的更永久!更改用户名迫使我不得不按预期在下一页视图上再次登录......这似乎很奇怪,它没有以相同的方式检查密码哈希。
  • @Stilgar - 我认为小偷可以在任何网站上完全、长期地访问我的帐户,即使我更改了密码,这是一个相当严重的安全问题。你说得对,PayPal 等人没有提供“记住我”选项,但许多网站确实提供了这个选项,而且在大多数情况下,我怀疑开发人员刚刚掉进了“成功的坑”由 .NET 的内置身份验证框架提供,并且不知道风险...

标签: asp.net security cookies forms-authentication


【解决方案1】:

也许只接受在您上次重置密码后发出的 FormsAuth 票证是有意义的。

因此,在 Global.asax AuthenticateRequest 中,从加密票证中提取 FormsAuthenticationTicket.IssueDate,并将其与用户上次重置密码的日期进行比较(当他们重置密码时,您需要将其存储在数据库中)。

如果票是在该日期之前签发的,则拒绝该票,不对其进行身份验证并要求他们重新登录。

我自己还没有实现这个,所以我可能在某个地方的理论中遗漏了一个漏洞......

【讨论】:

  • 我想知道cookie的IssueDate是否可以从客户端更改或认证系统会检测到它。
  • 不,IssueDate 是加密票证的一部分。
  • 是的,IssueDate 是加密 cookie 的一部分,因此客户端无法修改 - 所以是的,这里的一种解决方案是将票据 IssueDate 与帐户密码的日期进行比较最后更改,并拒绝在最近更改密码之前的任何票证。
  • 您可以做的另一件事是提高安全性 - 让用户再次输入密码以更改帐户电子邮件地址。如果有人在您上次重置密码后偷走了您的笔记本电脑,您不希望他们能够更改电子邮件地址,因为这会阻止您重置密码。通过这样做,您应该始终能够通过电子邮件重置您的密码,从而阻止他们再次进入(尽管可能为时已晚......)
【解决方案2】:

在身份验证 cookie 中有一个散列密码意味着您必须在每次请求时检查它。这将是低效的,因为身份验证可能很昂贵。

您可以针对表单 cookie 用户数据部分中涉及 id 的问题提供简单的“修复”。请注意,如果您自己创建 cookie,则可以在其中注入任意数据,例如密码的记录 ID。

现在,您可以在 global.asax 中添加 AuthenticateRequest 处理程序。您尝试从 cookie 中检索用户数据,并将从 cookie 中检索到的 id 与数据库中的 id 进行比较。如果它们不匹配,则返回错误和/或将用户从应用程序中注销。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-01
    • 1970-01-01
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 2014-01-22
    • 1970-01-01
    相关资源
    最近更新 更多