我正在为网站进行密码重置程序。正确的实现建议在数据库中存储一个随机加盐令牌哈希和到期日期。
但我遇到了一个不在数据库中存储令牌的解决方案: https ://stackoverflow.com/a/3165086/980737
我正在考虑使用上述内容,但使用 PASSWORD_BCRYPT 将 sha1() 替换为 password_hash()。
对我来说看起来不错,但我不是安全专家。上面没有数据库选项安全吗?如果不是为什么?
我正在为网站进行密码重置程序。正确的实现建议在数据库中存储一个随机加盐令牌哈希和到期日期。
但我遇到了一个不在数据库中存储令牌的解决方案: https ://stackoverflow.com/a/3165086/980737
我正在考虑使用上述内容,但使用 PASSWORD_BCRYPT 将 sha1() 替换为 password_hash()。
对我来说看起来不错,但我不是安全专家。上面没有数据库选项安全吗?如果不是为什么?
我认为链接的方法是“不安全的”。
该代码使用手动方法来尝试验证URL/令牌数据的完整性。这个想法是只有服务器(应该是唯一知道用户密码和盐的实体)才能生成给定的 SHA1;收到 URL 后,可以重新生成 SHA1,如果匹配,则解决方案建议 URL“必须”是服务器生成的,因此可以信任。
但是,上面的假设可能会被违反!如果 bcrypted/hashed 密码已知1则攻击者可以生成任意重置 URL并获得访问权限。这是因为攻击者拥有伪造他自己的“可验证”URL 所需的所有信息。
应用加密——在生成令牌之后,以避免像 Blender 指出的那样暴露信息——或者使用HMAC会增加所需的知识,因为使用额外的“服务器机密”来生成此类重置 URL。在执行客户端存储和返回数据的机密性和完整性检查的情况下使用加密和MAC 验证2。
但是,如果攻击者获知了这个额外的“服务器机密”,那么上述相同的问题仍然存在,并且可以随意生成虚假的重置 URL。(但在这一点上,我怀疑还有其他更紧迫的安全漏洞..)
至于 bcrypt 与 SHA1:由于输入空间巨大,没有必要切换- 此时密码应该已经被散列了!- 以及重置请求的有限超时。因此,在此处切换到 bcrypt 不会增加额外的安全性,并且使用 bcrypt 并不能缓解前面提到的问题。(另一方面,SHA1 对于实际的散列密码来说是一个糟糕的选择!)
1虽然帐户/密码信息永远不会泄露会很好,但密码散列的关键在于防止在发生此类泄露时 [大规模] 被利用。由于此类泄漏因此被视为“可能发生”的情况(并且确实发生了),因此额外的安全措施应该已经假定此类帐户/密码信息可能不会用作安全机密。
2 ASP.NET ViewState 安全/验证同时支持加密和完整性验证,这表明,通过可靠的实施和安全预防措施,无数据库/存储的方法可以在安全的企业环境中工作。
随机令牌应该是真正随机的。通过使令牌成为非随机数据的函数,您会泄露敏感信息。
如果您想自己实现,请生成一个安全的随机令牌:
$token = hex(openssl_random_pseudo_bytes(10, true));
并使其在 20 分钟或一个小时内过期。