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