2011-06-24 167 views
8

我错过了什么吗?是否有任何额外的步骤将密码存储到数据库?Web应用程序 - 存储密码

存放密码:
       关于这个问题尽可能我来,最好的方式来存储用户密码,在Web应用程序DB这个结论是经过大量的研究(在我的情况的MySQL + PHP)如下:

  • 指定一个站点范围的静态盐。 (16个字符,包括0-9,a-z,A-Z,[]/* - ')
  • 指定每个用户随机盐(存储在数据库中)。
  • 存储结果hash_function($ userPassword + $ sitewideSalt + $ randomSalt)
  • 将$ randomSalt与生成的散列一起存储。
  • 使用bcrypt调整工作量 散列

  • 攻击#1:攻击者通过SQL注入转储数据库。 我们hash_function的
            DB结果和每 用户盐随机。

    转储通过查询自己的帐户,攻击者可以 获得$ userPassword的$ randomSalt后。然后通过猜测散列 函数(如md5),他可以对 $ sitewideSalt开始彩虹攻击。但这可能需要长达1.41亿个 个世纪[1]。

    通过使用这种类型的安全不允许转储的数据库妥协存储的密码。用户仍然需要通过另一种方法找到$ sitewideSalt

  • 攻击#2:攻击者找到一个本地文件包含(LFI)载体。
             攻击者可以获取我们web应用程序的原始代码。

    通过可能LFI利用Web应用程序后 或RFI [2]的攻击者读取 源代码我们的web应用 并且获得我们简单 算法和存储
    $ sitewideSalt


在哪里下?
         现在攻击者有两种盐,他可以开始彩虹获得实际的密码。除了他必须为每个用户制作1个彩虹表,因为每个用户具有不同的随机用户特定盐($ randomSalt)。

“一个现代化的服务器可以计算出约330MB每秒的MD5 哈希值。如果 你的用户有密码这是 小写字母和6个 字符,你可以尝试每 一个可能的密码大小约为40秒的 。“
“...... CUDA,你可以放在一起你自己的小超级计算机集群,这将让你尝试周围7亿口令第二......” [3]

       ,我们现在需要做的是什么通过使用诸如bcrypt的耗时算法来扩展哈希函数。 bcrypt的工作负载因子可以是简单哈希函数的5-6个数量级。破解一个密码可能需要几年而不是几分钟。作为奖励,bcrypt已经为每个散列生成一个随机salt并将其存储在结果散列中。

  1. http://www.grc.com/haystack.htm
  2. http://www.wildcardsecurity.com/security101/index.php?title=Local_File_Inclusion

回答

3

不错的工作!对我来说看起来非常完整。

只有我会建议是:

旋转服务盐。

设计一种方法来周期性地轮换服务范围的盐,并定期运用它。

例如,在生成新服务盐后,将其用于所有新帐户&任何密码更改。当现有用户尝试登录时,使用旧的服务盐进行身份验证。如果成功,则使用新服务salt(以及可选的新用户特定盐)更新其哈希值。对于没有“登录一段时间”的用户,代表他们随机生成一个新密码。这将为已放弃网站的用户“保持”安全,迫使那些返回的用户使用密码重置功能。 ('有些时间'=你适应的任何时期)。

请勿硬编码您的服务盐。

不要让LFI攻击危害您的服务盐。在启动时向服务提供服务盐,并将其保存在内存中。为了危害服务salt,攻击者需要能够执行代码从内存中读取salt。如果攻击者可以做到这一点,那么无论如何你都能很好地处理。 =)

不要重复使用用户盐。

寻找机会为用户提供新的盐类。用户更改他的密码?生成一个新的随机盐。这进一步阻碍了暴力破解,迫使你的服务器范围内的盐应该是一个攻击者能够获得他的散列,只要他觉得喜欢它。加上这一点,请定期轮换你的服务 - 盐,我敢打赌,你对强制蛮力有很强的威慑力。

(将其标记为社区维基,如果其他人有其他想法)。

+0

我有点困惑。服务盐的逻辑如何用于认证?我猜我在mysql中存储服务盐,然后登录时,我将它附加到用户散列并存储散列,并检查它们是否相等。但是,是不是没有服务盐一样?因为如果用户散列和存储散列匹配,则附加服务盐也将匹配。 – 2012-07-25 05:11:45

+0

为什么你需要定期旋转盐? – sam

相关问题