使用.NET FormsAuthentication和持久性cookie改变密码的安全漏洞?

Dyl*_*tie 14 asp.net security cookies forms-authentication

好的,这是一个场景:

  1. Bob登录到使用.NET表单身份验证的mysite.com,然后勾选"记住我".
  2. Eve窃取了Bob的笔记本电脑
  3. 鲍勃得到一台新笔记本电脑,并更改了他的密码.

现在,在这一点上,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

Jon*_*noW 9

也许只接受上次密码重置后发出的FormsAuth票证才有意义.

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

如果在该日期之前签发了故障单,则拒绝该故障单,不对其进行身份验证并要求他们再次登录.

我自己没有实现这个,所以我可能在理论上错过了一个漏洞......

  • 不,IssueDate是加密票证的一部分. (3认同)

Wik*_*hla 1

在身份验证 cookie 中包含散列密码意味着您必须在每次请求时检查它。这将是低效的,因为身份验证的成本可能很高。

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

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