我错过了什么吗?是否有任何其他步骤将密码存储到数据库中?
存储密码:
经过尽可能多的研究,我得出的结论是,在Web应用程序数据库(在我的例子中是MySQL + PHP)中存储用户密码的最佳方法如下:
攻击#1: 攻击者通过SQL注入转储数据库。
DB结果
我们的hash_function和随机的每个
用户盐。
攻击后,攻击者可以 获取 $ userPassword 和 通过查找自己的帐户 $ randomSalt 。然后通过猜测哈希 像md5这样的功能他可以开始了 彩虹袭击了 的 $ sitewideSalt 即可。但这可能需要1.41亿 几个世纪以来[1]。
通过使用此类安全性 不允许转储数据库来破坏存储的密码 。用户仍需通过其他方法找到 $ sitewideSalt 。
攻击#2: 攻击者找到本地文件包含(LFI)向量。
攻击者可以获取我们的Web应用程序的原始代码。
通过可能的LFI利用Web应用程序之后
或RFI [2]攻击者读取
我们网站的源代码
申请并获得我们的简单
算法和存储的
的 $ sitewideSalt
下一步?
现在,攻击者拥有他可以开始彩虹的两种盐来获取实际的密码。除非他必须为每个用户制作1个彩虹表,因为每个用户都有不同的随机用户特定盐($ randomSalt)。
“现代服务器可以计算MD5 每秒大约330MB的哈希值。如果 您的用户拥有密码 小写,字母数字和6 人物长,你可以尝试每一个 单个可能的密码 在大约40秒内。“
”...... CUDA,你可以将自己的小型超级计算机集群放在一起,让你每秒可以尝试大约700,000,000个密码......“[3]
我们现在需要做的是使用耗时的算法扩展散列函数,例如bcrypt。 bcrypt的工作负载因子可以是更简单的散列函数的5-6个数量级。破解一个密码可能需要数年而不是几分钟。并且作为奖励,bcrypt已经为每个哈希生成随机盐并将其存储在结果哈希中。
答案 0 :(得分:3)
干得好!看起来非常完整。
我只有建议:
旋转服务盐。
设计一种方法,定期旋转服务范围的盐,并定期锻炼。
例如,在生成新的服务盐之后,将其用于所有新帐户&任何密码更改。当现有用户尝试登录时,使用旧服务盐对其进行身份验证。如果成功,则使用新服务盐(以及可选的新用户特定盐)更新其哈希值。对于未“登录”某段时间的用户,请代表他们随机生成新密码。这将为那些放弃您网站的用户“保持”安全性,迫使那些返回使用密码重置设施的用户。 ('某个时候'=你不熟悉的任何时期)。
不要对服务盐进行硬编码。
不要让LFI攻击危及您的服务盐。在启动时将service-salt提供给应用程序,并将其保存在内存中。为了破坏服务盐,攻击者需要能够执行代码以从内存中读取salt。如果攻击者能够做到这一点,那么无论如何你都会受到很好的冲击。 =)
不要重复使用用户盐。
寻找为用户提供新盐的机会。用户更改密码?生成一个新的随机盐。如果攻击者能够在他感觉到的时候能够获得他的哈希值,这进一步阻碍了暴力强制你的服务器范围的盐。结合这个经常旋转你的服务盐,我打赌你已经有强大的威慑力来反抗暴力。
(如果其他人有其他想法,请将此标记为社区维基)。
答案 1 :(得分:1)
使用BCrypt处理密码是唯一的步骤,或者更确切地说,包含以下内容:
您也忘了这个链接:http://codahale.com/how-to-safely-store-a-password/这是您引用的引用。