【问题标题】:crypt() breaks when migrating from PHP 5.2 to 5.4从 PHP 5.2 迁移到 5.4 时 crypt() 中断
【发布时间】:2013-07-10 00:34:49
【问题描述】:

我有一个在 PHP 5.2.10 版本上运行的系统不幸的是,最初的程序员误解了 crypt() 是如何实现的。

$crypt = crypt(trim($cuPassword), CRYPT_BLOWFISH); 
// The programmer thought this is how you configure a blowfish cipher

nb CRYPT_BLOWFISH 在这台机器上的值为零。

这可以产生一个随机的密码哈希值,例如 0$oZ534I2VvSw

今天,我将软件迁移到PHP 5.4.9,发现$crypt变成了*0,即由于salt无效导致的错误。

我的问题是我有一个无法再验证的登录密码表。我的问题:有没有一种方法可以重新创建在 5.2 版下运行的原始密码?当您将“0”作为盐传递时,实现了什么哈希?

【问题讨论】:

  • 进一步分析:它似乎默认为使用“0$”作为盐的 CRYPT_STD_DES。较新版本的 PHP 将其视为无效盐而拒绝。
  • 你在使用 Suhosin 补丁吗?因为这种行为不遵循我可以重现的普通 PHP 行为。

标签: php crypt


【解决方案1】:

你的描述并没有真正加起来。在 PHP 5.4.9 中,我对此进行了测试:

var_dump(crypt('hello', 0));

输出:

0$ny0efnQXFkE

现在在 PHP 5.5 中,调用 crypt('hello', 0) 时会得到 *0。不过没关系!因为这在 PHP 5.5 中仍然适用:this crypt('hello', '0$ny0efnQXFkE') == '0$ny0efnQXFkE'

您需要做的就是更改为新密码生成哈希的方式。验证现有密码将继续有效。

为了更好地衡量,在人们成功登录后,检查他们的哈希是否以 0$ 开头。如果是这样,请使用更新的正确 crypt 调用重新散列密码(因为他们输入了密码,您就知道它是什么)。

【讨论】:

  • 我的 5.4.9 版本 var_dump 给出 string(2) "*0"
  • crypt('hello', '0$ny0efnQXFkE') 也给了我 *0
  • 我假设你正在使用 Suhosin 补丁?
  • 补丁似乎没有激活。
  • @MortimerCat,它可能依赖于系统 crypt 库,但无论如何,0q 解决方案看起来像是可行的解决方案。我会确保在登录后重新散列旧密码。
【解决方案2】:

我尝试了所有有效的两位数字组合 (CRYPT_STD_DES),发现“0q”是等效的(几乎)。

PHP 5.2.10 地穴(修剪($cuPassword),CRYPT_BLOWFISH);

结果 = 0$txv6CWBxJ9Y

PHP 5.4.9 crypt(trim($cuPassword), '0q');

结果 = 0qtxv6CWBxJ9Y

我需要做的就是调整第二个字符,我可以再次匹配密码。

【讨论】:

  • 我只是独立尝试过,得出了同样的结论。
【解决方案3】:

不,您无法重新创建原始密码。否则即使是童子军也能打碎河豚。

您最好的机会是为您的用户生成一个随机密码并再次对其进行哈希处理,然后强制他们在登录后立即更改密码。

【讨论】:

  • 我不是想破解河豚,我只是想找到能像以前一样生成哈希的参数。
【解决方案4】:

根据 crypt(3),"$" 不是一个有效的盐值,因此您需要找到一个与 PHP/libc 曾经拥有的一样损坏的 crypt 实现:)

如果验证旧密码就足够了,请使用 Matthews 答案,否则尝试例如openssl 目前似乎仍然接受“0$”作为盐:

$ echo -n "secret" | openssl passwd -crypt -salt '0$' -stdin
0$z.PXBBy6uY.

【讨论】:

    猜你喜欢
    • 2017-12-29
    • 2020-01-14
    • 1970-01-01
    • 2016-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    相关资源
    最近更新 更多