"新密码无效"时WebSecurity.ChangePassword何时失败?

Col*_*lin 3 security asp.net-mvc-4 simplemembership

这是在MVC 4中支持的默认AccountController中更改密码的代码:

// ChangePassword will throw an exception rather 
//than return false in certain failure scenarios.
bool changePasswordSucceeded;
try
{
    string userName = User.Identity.Name;    
    changePasswordSucceeded = WebSecurity.ChangePassword(userName, 
                                                         model.OldPassword,
                                                         model.NewPassword);
}
catch (Exception)
{
    changePasswordSucceeded = false;
}

if (changePasswordSucceeded)
{
    return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
}
else
{
    ModelState.AddModelError("",
    "The current password is incorrect or the new password is invalid.");
}
Run Code Online (Sandbox Code Playgroud)

我的问题是消息不清楚.如果当前密码不正确那么没关系,但如果新密码无效,我想向用户提供更好的消息,告诉他们出了什么问题,我想更好地理解"失败情景",以便我可以定制消息.

这里的文档是关于异常的具体内容,我不认为这些内容应该在Action中被吞并并报告为无效密码.

那么为什么这里有"新密码无效"的可能性呢?如果我在我的应用程序中仅使用没有OAuth的SimpleMembershipProvider,我可以将其删除吗?

编辑: NB此数据注释也出现在"RegisterModel"类中,因此这里也有密码有效性检查

[StringLength(100, 
ErrorMessage = "The {0} must be at least {2} characters long.", 
MinimumLength = 6)]
Run Code Online (Sandbox Code Playgroud)

And*_*own 5

摘要

这是一个很长的答案,所以我把它编辑成了几个部分.与像rook这样的用户相比,我不是安全专家,甚至他说不相信他的安全答案,或者其他任何人.总是自己测试和理解它.任何阅读此内容 Web开发人员都应阅读OWASP十大Web安全漏洞,使用可信赖计算等在线指导,当然还有Bruce Schneier先生.对于我们任何人来说,安全性都很复杂且太大,因此请尽可能使用根据最佳实践进行工作的框架.首先,让这一切的观点.

有关这些摘要答案的更多详细信息,请参阅以

  1. 向用户发送的消息是故意模糊的,可以认为这是出于安全原因(见下文)
  2. 参考."故障情景",它们主要是由于无效的输入应该已经被模型验证,不正确的当前密码或边缘情况例外捕获
  3. 由于原始开发人员是懒惰的,或者因为他们认为所有案例都应该有一条返回消息(参见上面的1),所以例外被吞并并呈现为一个例外
  4. 只要您的属性匹配,或者比ChangePassword中的长度限制更具限制性, "新密码无效"可能不是您突出显示的代码的可能性.但是,见上文(1).
  5. 我可以删除它吗?见上文(1).
  6. 好点,见下面的讨论.

原始答案 - 概念攻击向量

从安全角度考虑它:

  • 我徘徊在你的手机/平板电脑/笔记本电脑上,坐在酒吧/咖啡店桌上(或家里/办公室的台式电脑)
  • 我想我可能知道你的密码
  • 我去"更改密码"并输入我认为您的密码不是
  • 我特意把一个1个字符的新密码放进去

机器告诉我

"当前密码不正确"

现在我再次尝试使用我认为您当前的密码:

"新密码无效"

我现在知道你的密码了,但你不知道我这么做,因为我没有改变任何东西.

脚注:我得到了第一组逻辑错误,删除它,编辑并重新发布,但是嘿 - 我不是布鲁斯

类似的攻击

这种攻击有很多种组合,但就像从糟糕的登录系统收集电子邮件一样.想想当我尝试使用电子邮件地址"恢复密码"时收到两条不同的消息会发生什么:

  • 电子邮件已发送到您的地址(对于您数据库中的电子邮件)
  • 找不到您的电子邮件(对于明显虚假的电子邮件地址)

那么我可以很容易找到您的网站有效成员的邮件对用户有针对性的钓鱼攻击,或者只是建立垃圾邮件的有效的电子邮件地址的列表.

可能的解决方案

在这两种情况下,我们更改密码的用户友好且同样安全的错误消息将是:

"当前密码不正确或新密码无效.请记住,您的密码区分大小写,新密码必须包含[ 64个字母/ 5个数字/ 4个字符/3个希腊神灵的名字]"

为了保持理智,请将其保留在您的应用程序使用环境中,但请记住,您在更大的生态系统中负有责任,并且用户在网站之间共享密码,无论您是否喜欢.

ChangePassword什么时候返回false?

关于ChangePassword何时返回false的问题部分:

基本上WebSecurity.ChangePassword:

总之,它返回false如果:

  1. 任何参数都会失败,空或长度检查; 要么
  2. 数据库连接失败; 要么
  3. UserId不再存在于数据库中; 要么
  4. 当前密码不正确; 要么
  5. (显然,changePasswordSucceeded = false如果发生任何其他异常,它将设置).
  6. 没有 newPassword调用内有效性检查ChangePassword

所以从理论上讲,如果你的验证属性正确到位,并且忽略了边缘情况,那么只有return false当我们有边缘情况时(用户已被删除,Get和Post之间,或者我们无法访问数据库) ,或当前密码无效).

即使在攻击者绕过浏览器中的UI(他们将会)按照Action本身调用IsValid模型的情况下,这一切都是正确的.

客户端消息

这里有一个严肃的免责声明:我不会把自己的生命花在安全上.我遵循安全设计原则(例如,我跟上OWASP十大项目),并相信我对最重要的安全原则有很好的认识.因此,我可能有一些错误.

如果客户端"密码要求"验证不存在 - 会发生什么?用户必须等待Post返回才能找出发生的事情.

如果客户端"密码要求"验证那里,它会削弱我们的界面吗?我不相信:

  • 服务器仍然执行要求和当前密码验证
  • 服务器不区分两种故障情况(实际上它确实如此,见下文)
  • 因此,服务器只会告诉您当前密码是否有效,以及密码因此更改.
  • 希望该网站还:
    • 防止更改回旧密码
    • 发送一封电子邮件通知,告知您的密码已被更改(可能需要等待15分钟,以防止攻击者将您的手机中的电子邮件从打开的电子邮件中删除,并且在我们的网站中打开的电话中解锁,并且我们的电子邮件也开放了)

MVC不会,AFAIK,做这些事情中的任何一个,所以这就是它开始分崩离析的地方.

它也会因为Model.IsValid操作中的测试而从服务器返回不同的错误和消息,因为它会强制执行新的密码验证以及针对此失败的不同错误消息.因此,在其当前实现中,单个错误消息方法是有缺陷的.

摘要

那么我会改变这一切的方式吗?在希望,我会提高时间的其他部分,我可能不会,不是改变返回消息是有点长,更多的信息等.

这是个人意见,可以反过来说


细节:

实际的提供程序实现变得复杂.为SimpleMembershipProvider,例如,

  • 它可能会将调用传递给"之前的提供者",如果尚未初始化的话.
  • 否则,如果密码/用户名为空,空,太长等,它可能会抛出ArgumentExceptions(冒泡到catchreturn falseMembershipUser.ChangePassword).
  • 如果那不会发生那么它会
    • 尝试UserId从数据库中获取(如果失败则返回false),
    • 检查当前密码是否正确(如果失败则返回false),
    • 最后使用UPDATE查询更新密码,PasswordChangedDate并为其设置
  • 然后它更新内部数据 MembershipUser