OWASP为什么不建议在客户端和服务器上同时解密密码?

lmc*_*iro 5 security authentication passwords owasp

由于GitHub和Twitter最近的问题:

我想知道,为什么不在客户端和服务器上同时解密密码的最佳实践?由于我不会更改已经是服务器端最佳实践的任何内容(盐,强哈希,HTTPS),因此只能更加安全。服务器将已散列的密码视为密码,并在存储之前再次对其进行散列。

  • 万一引发异常时我记录了整个请求,如果登录/注册请求中发生异常,我将永远无法访问用户纯文本密码
  • 我知道,如果有人可以通过MITM(许多公司在其专用网络中替换SSL证书)或日志或恶意服务器管理员来访问这些仅在客户端隐藏的密码,则他们将能够使用它在我的网站中进行身份验证,但无权访问纯文本密码,因此它绝不会损害其他站点和服务中的用户帐户(即使是那些重复使用密码的用户)

Dan*_*Dan 2

我正在寻求解决类似的问题,即可以在服务器上记录纯文本密码。结论是,如果可以的话,您应该始终另外对客户端密码进行哈希处理

以下是一些有关客户端加服务器哈希的文章:

客户端加服务器密码散列作为一种潜在方法,可以在不使服务器过载的情况下提高抵御暴力攻击的安全性

加盐密码哈希 - 正确执行

具体参见:

在 Web 应用程序中,始终在服务器上进行哈希处理

如果您正在编写 Web 应用程序,您可能想知道在哪里进行哈希处理。密码应该在用户浏览器中使用 JavaScript 进行哈希处理,还是应该“以明文形式”发送到服务器并在那里进行哈希处理?

即使您在 JavaScript 中对用户密码进行哈希处理,您仍然必须在服务器上对哈希值进行哈希处理。考虑一个网站,该网站在用户浏览器中对用户密码进行哈希处理,而不在服务器上对哈希值进行哈希处理。为了验证用户身份,该网站将接受来自浏览器的哈希值,并检查该哈希值是否与数据库中的哈希值完全匹配。这似乎比仅在服务器上进行散列更安全,因为用户的密码永远不会发送到服务器,但事实并非如此。

问题在于客户端哈希逻辑上成为用户的密码。用户进行身份验证所需要做的就是告诉服务器其密码的哈希值。如果坏人获得了用户的哈希值,他们可以使用它来向服务器进行身份验证,而无需知道用户的密码!因此,如果坏人以某种方式从这个假设的网站窃取了哈希数据库,他们将可以立即访问每个人的帐户,而无需猜测任何密码。

这并不是说您不应该在浏览器中进行散列,但如果您 这样做,您绝对也必须在服务器上进行散列。在浏览器中进行散列当然是一个好主意,但 在实施时请考虑以下几点:

客户端密码哈希不能替代 HTTPS (SSL/TLS)。如果浏览器和服务器之间的连接不安全,中间人可以在下载 JavaScript 代码时修改它,以删除哈希功能并获取用户的密码。

某些 Web 浏览器不支持 JavaScript,而某些用户则在浏览器中禁用 JavaScript。因此,为了获得最大的兼容性,您的应用程序应该检测浏览器是否支持 JavaScript,如果不支持,则在服务器上模拟客户端哈希。

您还需要对客户端哈希值加盐。显而易见的解决方案是让客户端脚本向服务器询问用户的盐。不要这样做,因为这会让坏人在不知道密码的情况下检查用户名是否有效。由于您也在服务器上进行散列和加盐(使用良好的盐),因此可以使用用户名(或电子邮件)与特定于站点的字符串(例如域名)连接作为客户端盐。

经过研究,对客户端进行哈希处理似乎也具有明显的安全优势。如果通过 HTTPS 的密码被泄露或者密码登录到服务器上,则纯文本密码将无法轻松地在用户的其他帐户上重复使用(许多用户重复使用其密码)。

唯一可能的缺点是客户端性能和服务器端密码验证。用户可以操纵您的客户端 JS 并提交“弱”密码。服务器不会知道更多。但我认为这是一个小问题,它依赖于人们故意修改他们的客户端代码以削弱他们自己的安全性。