PHP安全性 - 在散列密码被破坏时检查用户帐户

时间:2014-01-29 08:55:08

标签: php security hash password-protection whirlpool

目前我只是在玩弄PHP,但我想到了一个想要扩展的想法,需要知道你认为它有多安全,以及我如何改进它以使它可以接受实际使用

这是我将密码存储在数据库中的方式:

纯文本密码 - >哈希密码(我使用whirlpool,但任何方法都会有效) - > shuffle / scramble哈希密码(使用str_shuffle()函数)。

我将用户密码存储在数据库中,以确保数据库是否被泄露,这将使攻击者无法撤消数据库中破解的密码哈希。 (因为在某种意义上你怎么能反转,使用哈希的随机文本? - 虽然我确信你可以通过比较共享相同字符的哈希列表来创建一个可能性列表。)

我检查他们在登录表单上输入的用户密码是否正确(与数据库中的损坏哈希值相比)的方法是计算两个字符串/密码中的单个字母+数字(af& 0-9) ,看看他们是否匹配,如果他们匹配,我认为他们已经正确登录。

同样,我想知道您认为这有多安全,如何改进它以使其可以接受实际使用。 (如果可能的话。) &安培;我也想尽我所能避免"可逆"哈希值。 (即创建我自己确保密码匹配的方法的想法,我想让它更像是一个最好的猜测假设,完全帮助确保攻击者无法撤消数据库中的密码。

&安培;是的,我知道这是愚蠢的,因为它很可能导致更多的安全漏洞,而不是帮助解决它们。但这只是我所愚弄的事情,也许是希望让它变得实用。


其他信息:

1)密码与唯一的盐一起存储(因此,不是1个帐户共享相同的盐)

2)密码盐总是在变化(每次用户帐户成功登录时,都会更改数据库中的用户盐。我这样做是为了更改数据库中的哈希,导致密码冲突减少频繁(希望)并且还防止不需要的用户多次使用相同的错误密码登录(如果他们设法遇到一个,只有这样才能实现这一目标是通过强力或猜测任何登录系统容易受到影响。)

当我说密码冲突时,我的意思是“"你好" &安培; "蓝色"共享相同的字符数(正如我所解释的,我会计算各个字符+数字,并将它们与ASSUME进行比较,以确定其正确的密码。)

3)我也可以保留散列密码的前3个/数字不受str_shuffle影响,以帮助确保密码正确。 (通过创建2个检查,1)检查两个字符串是否共享相同的FIRST 3 CHARS / Numbers& 2)然后比较每个字符串中的字符数。 (希望再次减少密码冲突)。

4)显然会增加其他安全措施(即最大登录尝试次数,验证码等等),以帮助防止自动强制执行,使黑客更难找到可能的密码或真实密码。

我已经取得了成功的PoC,虽然我还没有针对字典攻击/暴力攻击测试PoC,但看起来存在密码冲突的可能性。 &安培;他们有多频繁。

如果我说过很多“无用的”'信息,忽略它。我只是尽力合理地解释这一点。

4 个答案:

答案 0 :(得分:2)

这对我来说似乎非常无效和不安全。

最值得注意的是:碰撞。你在其他信息中已经提到了这一点。

只需检查散列和放大器中字符的数量。混乱让碰撞概率通过屋顶。您启用一个密码对其哈希的所有排列也有效。考虑到漩涡散列中128个字符的长度,这是一个非常大的数字。

所以,基本上,通过允许这个,你允许一个想成为的暴​​力破坏者一次检查几千个密码,输入一个。

他们无法获得对系统的永久访问权限,因为您说您在每次登录后都更改了哈希值,但是他们获得访问权限的可能性大大增加。

关于盐的改变......你是怎么做到的?除非你在哈希之后而不是之前使用盐,否则我想不出办法,这不是盐在哈希中的工作方式。

如果您想让它更安全,那么只需使用多个哈希迭代。存储散列密码和散列迭代次数。每次用户再次登录哈希时,都会存储它,并增加迭代次数。这将充分改变存储的哈希,而不会引入太多的加密弱点。

答案 1 :(得分:0)

您的改组方案会降低密码的安全性。比较洗牌后字母和数字的实例数增加了两个人拥有相同密码值的机会(碰撞,如你所说)。

重新腌制是你可以使用的东西。每次用户成功登录时,您都可以重新设置密码并再次保存。如果您修改PHP密码过程以使用高分辨率时间值,增加唯一性,这可能会更好。基本上你不断旋转密码的盐。您必须保存清除密码,将其哈希值与保存的密码进行比较,重新盐化并散列清除密码并再次保存。

答案 2 :(得分:0)

加密强哈希函数的输出对于所有意图和目的已经是伪随机的。尝试通过加扰来添加熵什么都不做。它不会使哈希变得“可逆”,因为“反转”哈希的唯一方法是选择输入,对其进行散列,将其与哈希进行比较;记录用户时必须执行的操作与攻击者必须执行的操作相同,更改比较算法不会更改此基本操作。 (正如其他人所指出的,你的弱化比较算法实际上帮助了攻击者。)

处理这个问题的公认方法已经足够了:

  1. 通过使用(伪)随机噪声对其进行腌制,确保您的输入是唯一的,这会迫使攻击者进行实际的强力散列。
  2. 选择一个缓慢的哈希值(最好是bcrypt或scrypt,具有足够高的成本因子,使你可以做一次,但攻击者无法进行数十亿次),这使得它在计算上不可行。攻击者在他的一生中蛮力地使用哈希。
  3. 如果两个步骤都正确完成,那么“反转”哈希就已经不可行了。不需要额外的心灵游戏。

答案 3 :(得分:0)

不要再纠缠于你的想法了。这是不安全的。

密码安全只有两种方法可以提供足够的抗篡改能力:

  1. 使用硬件安全模块执行类似HMAC-SHA1的操作。该模块是外部硬件,外部世界不知道模块内部的内部秘密(仅通过物理访问模块),如果没有该模块,生成的哈希将永远不会被重建。使用具有“快速”散列算法的专用硬件使其成为批量密码检查的可行解决方案。有关详细信息,请参阅http://en.wikipedia.org/wiki/Hash-based_message_authentication_code
  2. 使用非常慢的哈希算法。诸如“scrypt”或“bcrypt”之类的东西执行速度非常慢,从而阻碍了针对已知哈希列表的密码列表的快速强力扫描。 PHP目前只支持“bcrypt”。
  3. 您可能想知道为什么要使用封装秘密的外部硬件。简单:可以从正在执行哈希的计算机上访问的任何内容都可以被盗。窃取秘密就像对所有密钥使用相同的盐(或根本没有):最终“只”拥有一个非常快速的哈希算法,并且每个其他组件都已知,并且可以立即开始强制密码。

    因此,如果没有专用硬件,唯一的另一种选择是慢速密码哈希算法。

    PHP有一个解决方案:password_compat是一个为PHP 5.5之前的版本重新实现PHP密码哈希API的库。如果您已经在使用5.5,则只需使用these functions