【发布时间】:2011-09-21 19:43:04
【问题描述】:
我错过了什么吗?是否有任何额外的步骤将密码存储到数据库?
存储密码:
在对该主题进行尽可能多的研究之后,我得出的结论是,将用户密码存储在 Web 应用程序数据库(在我的情况下为 MySQL+PHP)中的最佳方法如下:
- 分配站点范围的静态盐。 (16 个 rand 字符,包括 0-9、a-z、A-Z、[]/*-')
- 为每个用户分配一个随机盐(存储在数据库中)。
- 存储结果 hash_function($userPassword + $sitewideSalt + $randomSalt)
- 将 $randomSalt 存储在生成的哈希旁边。
- 使用 bcrypt 可调工作负载 散列
-
攻击 #1: 攻击者通过 SQL 注入转储数据库。
数据库结果 我们的 hash_function 和随机数 用户盐。在转储之后,攻击者可以 获取 $userPassword 和 $randomSalt 通过查找他自己的帐户。然后通过猜测哈希 诸如md5之类的功能他可以启动一个 彩虹攻击 $sitewideSalt。但这可能需要高达 1.41 亿 世纪[1]。
通过使用这种类型的安全性不允许 DB 转储危及存储的密码。用户仍然需要通过其他方法找到 $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 已经为每个散列生成了一个随机盐,并将其存储在生成的散列中。
【问题讨论】:
标签: passwords security hash salt