是否应该对 2FA 密码进行哈希存储?

Posted

技术标签:

【中文标题】是否应该对 2FA 密码进行哈希存储?【英文标题】:Should 2FA secret codes be hashed for storage? 【发布时间】:2018-02-13 18:14:12 【问题描述】:

我正在我们的网站上使用 Google Authenticator 实施 2FA。如果我理解正确,每个用户都会有自己的密码,我需要在登录时验证他们输入的 6 位数密码。

将这些密码与用户密码存储在同一个数据库中似乎是个坏主意(尽管,如果有人掌握了数据库,我们就会遇到更大的问题),还有其他方法吗?还是应该将它们视为密码并加密?

【问题讨论】:

【参考方案1】:

您无法对用于生成 Google Authenticator 的 TOTP 代码的密钥进行哈希处理,因为您需要原始密钥才能实际生成代码。

正如您所说,如果有人拥有您的数据库,那么无论如何您都会遇到更大的麻烦。然而,这就是 2 因素身份验证应该如何工作的方式。如果密码确实被安全地散列并且攻击者只有 TOTP 秘密,那么他们所能做的就是在登录所需的 2 个因素中生成 1 个,并且他们还有更多工作要做来破解或窃取密码。

如果您不想担心为您的用户存储这些秘密并让第三方处理它,我建议您看看Twilio's Two Factor Authentication API。全面披露,我为 Twilio 工作,但如果您不想担心查看无法散列的秘密,以及利用其他东西,例如 Authy app(包括没有 QR 码的秘密传输)和extra device data that is now available with authentications 那么它可能会很有趣。

【讨论】:

【参考方案2】:

你是对的。

2FA确实增加了用户的安全性,但从定义上说在服务器端并没有那么强。如果具有数据库访问权限的黑客或恶意员工转储并发布用户机密,则额外的安全性就消失了。

可以做什么? 您可以创建一个外部隔离微服务,接收用户哈希并生成 2FA 密钥,对其进行加密并存储在键值数据库中,如弹性搜索。您可以在服务器启动后动态设置加密密钥,而不是硬编码存储它。您可以将数据库存储在员工只能通过 API 访问的外部服务器上。

这样,如果恶意行为者转储 elasticsearch 数据库,他们就无法知道秘密是什么,即使他获得了对加密密钥的访问权,他也不知道使用该秘密的用户是谁,因为密钥是用户 ID 哈希(不是用户 ID)。

没有什么是完美的,但 2FA 的目标是让攻击者更难取得成功。我认为它有帮助。

【讨论】:

【参考方案3】:

我希望这些双因素代码有严格的时间限制(例如:5 分钟),在我看来,这是一个足够的缓解措施。例如,获得数据库的黑客在获得访问权限后只能在很短的时间内使用代码。老实说,他不太可能在那个时间范围内获得任何用户的第一个因素(密码)(假设您不进行密码散列the wrong way),因此第二个因素在这种情况下甚至不会发挥作用。

(此论点与6位代码的暴力搜索空间非常小这一点无关)

如果它们没有时间限制,那么您应该考虑实现自己的超时而不是散列值。散列更适合具有较长生命周期的数据。

【讨论】:

问题是关于OTP secret,它的寿命很长。你说的是生成的代码。

以上是关于是否应该对 2FA 密码进行哈希存储?的主要内容,如果未能解决你的问题,请参考以下文章

我应该使用什么哈希算法来存储密码?

哈希的意义何在?

使用 Node.js 和 MongoDB 存储密码

存储用户名和密码的最佳方式

如何将密码文本与 bcrypt 哈希值进行比较?

在缓存中安全地存储密码哈希