具有挑战性的挑战:客户端密码散列和服务器端密码验证

信息安全 Web应用程序 javascript bcrypt pbkdf2
2021-08-15 07:58:16

我们有一个网站,用户需要登录才能访问特权信息。显然我们正在使用 SSL,但我也想避免明文密码意外地出现在服务器日志中,或者管理员的视线。因此,我想使用 Javascript 实现客户端散列。

此外,我想避免泄露具有相同密码的用户对,因此使用特定于用户的盐。最后,我想在混合中添加一个随机挑战(又名随机数),以确保窃听者*不能使用最终哈希作为新的“密码”。在开始密码散列之前,我将额外往返网络服务器以获取盐和挑战。*) 是的,我们正在使用 SSL,但作为深度防御,我希望使实施尽可能可靠。

尤其是挑战具有挑战性。我所知道的唯一可行的实现是首先计算最终的密码哈希(使用 bcrypt、scrypt 或 PBKDF2),然后使用挑战进行一轮额外的 sha256_hmac。在服务器端,我们从数据库中获取密码哈希并执行相同的附加 sha256_hmac 并比较结果。

但是,以上内容意味着完整的密码哈希计算必须在 Javascript 客户端完成,因为挑战中的哈希应该始终是最后一步。在旧版(?)iPhone 3G 上,只能在 2 秒内完成 6 轮 bcrypt 或 5000 轮 PBKDF2-SHA256,这是我们可以容忍的最大延迟。

问题 #1:我是否正确,现在 bcrypt 应该至少 12 轮,而 PBKDF2-SHA256 至少 5000 轮?所以我应该选择5000轮的PBKDF2-SHA256?

问题 #2:是否存在可以在流程早期运行的质询-响应机制(例如,在一次散列密码上),所以我可以将 bcrypt/PBKDF2 加固留给网络服务器?

问题#3:假设不存在这样的质询-响应机制,是否最好放弃我的质询-响应要求,只应用用户特定的盐客户端并彻底强化服务器端?与使用挑战-响应机制和更少的回合相比,这会导致整体更强大的系统吗?

编辑:总结下面关于客户端散列安全性的长期评论:普遍意见似乎是增加的复杂性是不值得的,最好把精力放在审计服务器端代码上并限制不受信任的员工的服务器端访问。

4个回答

我认为您在浪费时间并增加不必要的复杂性。我认为您给出的理由不足以保证这种客户端密码散列机制。

相反,我建议保持简单。通过 SSL 加密的链接发送密码。谈到安全性,简单就是好的。不必要的复杂性是安全性的敌人,因为它引入了错误和错误的机会。

节省您的精力用于解决更现实威胁的其他安全任务。人们可以花在提高安全性上的时间、精力和预算是有限的;最好把它花在能带来最大收益的地方(考虑到投资,安全性的最大改善)。我认为您会发现还有其他方法可以用来强化系统,从而进一步提高安全性。

如果您担心服务器端代码是否正确处理密码,请仔细检查该代码:它应该包含在非常小的代码块中。这应该注意诸如服务器记录明文密码之类的风险:您只需阅读涉及密码检查或读取密码的每一行代码,确保它所做的第一件事是适当地散列密码,然后确保它所做的只是检查密码的有效性并返回真或假。如果您的系统设计良好,那么通过代码审查来验证应该非常简单。如果代码设计得不好,也许现在是修复它的好时机。

如果您还没有这样做,您可能需要查看 SRP。如果您想要一个挑战/响应类型的系统,它应该满足您的所有要求。

http://en.wikipedia.org/wiki/Secure_Remote_Password_protocol

我会警惕任何自制的协议。我也会警惕任何基于客户端散列的身份验证协议。最好的办法是研究NTLM 身份验证针对此协议的大量攻击。比如NTLM 弱随机数漏洞

(SRP 还不错,SRP-TLS 看起来很酷。)

  1. 不,你还是太小了。OWASP 密码存储备忘单建议在 2012 年进行 64,000 次 PBKDF2 迭代,并且每 2 年翻一番 (https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet)。

  2. 请参阅上面的其他答案。

  3. 您确实可以选择在客户端进行一些散列(例如,2,000 轮 PBKDF2_SHA-1),然后一旦结果到达服务器,通过另一组大散列(例如,300,000 轮 PBKDF2_SHA- 512),并比较该最终值。

您的数据库仅存储最终的双 PBKDF2 值。

您的 Web 日志文件和/或可能较弱的 SSL 会话使用中间单 PBKDF2 值。虽然这个中间值肯定比最终值弱得多,但它仍然比明文强得多。

请注意,您还需要检查用户在更改密码/选择新密码时针对具有一些规则的普通破解字典提出的密码(小写以消除大小写游戏,在单词后添加 1 到 1000 的数字,在单词后添加日期,基本的 1337 口语翻译等)以防止“强”密码“P@$$w0rd”(大写、小写、符号和数字 - 8 个字符长,它必须非常强!)出现。