Web应用程序 - 存储密码 [英] Web Application - Storing a Password

查看:126
本文介绍了Web应用程序 - 存储密码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我错过了什么?是否有任何额外步骤将密码存储到数据库?



存储密码:

    ; 经过尽可能多的关于这个主题的研究,我得出结论,将用户密码存储在Web应用程序数据库(在我的例子中为MySQL + PHP)中的最佳方式如下:




  • 分配一个站点范围的静态盐。 (16 rand chars incl 0-9,az,AZ,[] / * - ')

  • 为每个用户分配一个随机salt(存储在数据库中)。 $ b
  • 存储结果hash_function($ userPassword + $ sitewideSalt + $ randomSalt)

  • 将$ randomSalt与生成的散列一起存储。使用bcrypt可调工作负载
    散列







  • 攻击者1: 攻击者通过SQL注入转储数据库。

         DB结果
    我们的hash_function和随机每
    用户salt。

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

    通过使用这种类型的安全性, 不允许转储的数据库损害存储的密码 。用户仍然需要通过其他方法找到 $ sitewideSalt

    #2: 攻击者找到本地文件包含(LFI)向量。

        攻击者可以获取我们Web应用程序的原始代码。


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





  • 下一步要去哪里?

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


    一个现代服务器可以计算每秒大约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. ol>

      解决方案

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



      只有我会有的建议是:

      旋转服务盐。



      设计一个定期轮换服务范围内盐的方法,并定期执行。



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



      不要硬编码你的服务盐。



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



      不要重复使用用户盐。

      寻找机会给用户新的盐。用户更改他的密码?生成一个新的随机盐。这进一步阻碍了暴力破解,迫使你的服务器范围内的盐应该是一个攻击者能够获得他的散列,只要他觉得喜欢它。加上定期旋转你的服务 - 盐,我敢打赌,你已经有了一个强大的威慑力量反对暴力。



      (标记为社区wiki应该其他人有更多的想法)。


      Have I missed anything? Are there any additional steps storing passwords to the DB?

      Storing the Password:
          After as much research on the subject as possible I've come to the conclusion that the best way to store user passwords in a web application DB (in my case MySQL+PHP) is as follows:

      • Assign a sitewide static salt. (16 rand chars incl 0-9,a-z,A-Z,[]/*-')
      • Assign a per user random salt (stored in the DB).
      • Store the result hash_function($userPassword + $sitewideSalt + $randomSalt)
      • Store the $randomSalt alongside the resulting hash.
      • Use bcrypt adjustable workload hashing

      • Attack #1: Attacker dumps the DB via SQL Injection.
            DB results of our hash_function and the random per user salt.

        After the dump the attacker could obtain $userPassword and $randomSalt by looking up his own account. Then by guessing the hash function such as md5 he could start a rainbow attack on the $sitewideSalt. But that could take up to 1.41 hundred million centuries[1].

        By using this type of security does not allow a dump of the DB to compromise stored passwords. The user still has to find the $sitewideSalt through another method.

      • Attack #2: Attacker finds a Local File Inclusion (LFI) vector.
            Attacker could obtain the raw code for our web application.

        After exploiting the web application through a possible LFI or RFI[2] the attacker reads the source code for our web application and obtains our simple algorithm and the stored
        $sitewideSalt.


      Where to next?
          Now the attacker has both of the salts he can begin to rainbow to obtain the actual passwords. Except he must make 1 rainbow table for each user as each user has a different random user specific salt ($randomSalt).

      "A modern server can calculate the MD5 hash of about 330MB every second. If your users have passwords which are lowercase, alphanumeric, and 6 characters long, you can try every single possible password of that size in around 40 seconds."
      "...CUDA, you can put together your own little supercomputer cluster which will let you try around 700,000,000 passwords a second..."[3]

          What we need to do now is extend the hashing function by using a time consuming algorithm such as bcrypt. bcrypt's work load factor can be 5-6 orders of magnitude that of the simpler hashing functions. Cracking just one password can take years instead of minutes. And as a bonus bcrypt already generates a random salt for each hash and stores it in the resulting hash.

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

      解决方案

      Nice work! Looks very complete to me.

      Only suggestions I would have are:

      Rotate the service salt.

      Design a method to periodically rotate the service-wide salt, and exercise it regularly.

      For example, after generating a new service salt, use it for all new accounts & any password changes. When an existing user tries to log in, authenticate them with the old service salt. If successful, update their hash with the new service salt (and optionally a new user-specific salt). For users who don't log in for 'some time', randomly generate a new password on their behalf. This will 'keep up' security for users who've abandoned your site, forcing those that return to use the password reset facilities. ('some time' = whatever period you're comfortable with).

      Don't hard-code your service salt.

      Don't allow a LFI attack to compromise your service salt. Feed the service-salt to your application at start up, and keep it in memory. To compromise the service salt, an attacker would need to be able to execute code to read the salt from memory. If an attacker can do that, you're pretty well hosed anyway. =)

      Don't reuse a users salt.

      Look for opportunities to give users new salts. User changes his password? Generate a new random salt. This further hampers brute forcing your server-wide salt should an attacker be able to obtain his hash whenever he feels like it. Couple this with regularly rotating your service-salt, and I'd wager you've got a strong deterrent against brute-forcing.

      (Marking this as a community wiki should others have additional ideas).

      这篇关于Web应用程序 - 存储密码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆