2011-03-10 86 views
9

我想我在这里失去我的弹珠......我的网站有一个问题,随机停止接受登录。我现在已经能够将它跟踪到crypt(),表现得非常奇怪。PHP crypt()返回错误的答案

在我的数据库中,我有用户密码的加密版本 - 所以我们来说说Og12345678。

当用户登录时,他们输入密码,我从数据库中读出盐,然后隐藏他们输入的内容并进行比较 - 通常这很有效。

所以我在做crypt($ enteredPassword,$ saltFromDb) - 在这种情况下,盐当然是Og。通常对于给定的用户密码crypt可以正常工作。

当事情出错了(当他们这样做的时候,它是一个永久的变化,直到我重新启动Apache),我发现crypt开始为相同的输入返回一个不同的答案与相同的盐。

但是它是一致的,即一旦系统出问题隐藏返回错误的答案,但它总是返回相同的错误的答案。重复刷新页面显示相同的输出。同样的盐也在新的不正确的地穴结果中也有证据,所以并不是盐在某处失踪。

如果我然后重新启动Apache并重新运行脚本而不做任何更改,那么crypt的结果会回到它们应该如何的结果。我很感激它不是最新的PHP(5.2.8),但会重视任何观点,包括它是否是一个已知的错误修复在更高的版本(升级PHP并不是一个快乐的任务,有很多网站,其中一些仍然使用不幸的怪癖,每次升级都需要重新测试) - 如果它是一个已知的固定错误,那么显然我会尽快升级它,除此之外它可能会更容易从外部外包crypt,因为我只是在我的网站的一个共同的地方使用它。

任何输入赞赏。

马特Peddlesden

---更新:2011年3月11日

修正评论先前给出的有关操作系统... - 操作系统为Windows Server 2008 SP1 64位。道歉我应该加倍检查,而不是假设我能记得!该机是戴尔2950 8GB Ram,至强处理器。我开始思考Krtek提出的建议 - 当系统已经不可靠时,如果我生成新的crypt()(即一个非常简单的例子,我将一个变量设置为一个字符串,然后比较它与地穴) - 一切都很好。当我重新启动服务器时,再次回到以前的计算。所以我绝对倾向于改变算法用于计算crypt()结果 ...有什么想法可能会导致这种情况发生?我打印出CRYPT_STD_DES等的值,它们在重新启动之间不会改变。

任何人都有什么线索可能会导致这种情况发生?

无论昨天在一天中发生了两次,最奇怪的是。

感谢迄今为止的答案。

---更新:2011年3月16日

只是想提供另一个更新。

这仍然发生,仍然没有进一步理解为什么。

如果将来有人遇到这种情况,我认为我的解决方案将会做一些讨厌的攻击,将所有crypt()执行推送到外部C#应用程序,并停止依赖PHP做他们。某处出了问题,在这一点上,我能看到的唯一解决方案就是完全从等式中移除它。

当然,如果它仍然发生,这将是有趣的知道呢! :)

谢谢大家。

+1

我认为这是不太可能,这是你的问题,但我看到PHP文档中的建议 - http://php.net/manual/en/function.crypt。PHP的 - 是你应该将整个(盐)加密的密码作为盐传递。 '如果(crypt($ enteredPassword,$ cryptedPasswordFromDB)== $ cryptedPasswordFromDB){...}'。这一点似乎是,然后crypt()可以从$ cryptedPasswordFromDB确定正在使用的哈希算法。再次,我怀疑这是你的问题的原因,但你可能会给它一个去... –

+1

是否有可能比脚本更改一些PHP配置导致crypt使用不同的哈希函数?就像@Gareth所说的从db传递完整的密码可以解决这个问题。 – krtek

+0

我开始按照Krtek的建议思考 - 当系统变得诡异时,如果我生成新的crypt()(即一个非常简单的例子,我将一个变量设置为一个字符串,然后将其与crypt ) - 所有的作品都很棒。当我重新启动服务器时,又重新开始工作了。所以我绝对倾向于改变用于计算crypt()结果的算法......对于可能导致这种情况发生的任何想法?我打印出CRYPT_STD_DES等的值,它们在重新启动之间不会改变。 –

回答

1

这可能是影响你的crypt()函数的Suhosin PHP安全补丁。它改变了很多加密/随机方法,可能是你的问题的原因。

检查phpinfo()并查看'suhosin'是否在页面上的任何位置。如果它在那里,请查看在php配置中禁用它的一些功能。

+0

感谢您的意见,我已经检查了phpinfo(),它没有任何提及的suhosin位,所以我认为这不适用。 –

2

你为什么要读盐?你怎么得到盐?不同的算法使用不同的方法在输出中包含salt。

只需使用地穴功能的全输出作为第二个参数:

$crypted='Og12345678'; 
    if (crypt($_POST['password'], $crypted)==$crypted) { 
     .... 

而且单次DES?真?

上次我查了一下,PHP crypt实现会调用系统提供的crypt()函数 - 所以如果它具有broekn,那么它更可能是你的操作系统而不是PHP--但是你没有说出你的OS是。

+0

操作系统是Windows Server 2008 SP2。感谢您的意见。 –

+0

只允许我添加单行注释:) - 我调整了代码以在crypt()命令中使用完整密码,并且这在刚刚系统再次出错时没有帮助。 –

+0

是的,一次通过DES,系统是很久以前写的,说实话它不保护任何东西,甚至是远程安全的,它只是让人们从网站上下载文件。整个网站在某个时候需要重新开发新技术。但是,是的,指出:) –

0

我面临同样的问题。由于将vTigerCRM安装移至本地计算机,因此用户以前存储的密码登录失败。这似乎是的crypt()将返回在不同环境下不同的哈希有相同的参数:

在本地环境:

SYSTEM: Windows NT 6.1 build 7601 (Business Edition Service Pack 1) i586 
PHP: 5.3.5 

crypt('hello world','$1$ad0000000'): 

    $1$ad00000008tTFeywywdEQrAl9QzV.M1 

在生产环境:

SYSTEM: Linux 2.6.18-338.9.1.el5.lve0.8.32 #1 x86_64 
PHP: 5.3.5 

crypt('hello world','$1$ad0000000'): 

    $1$ad000000$8tTFeywywdEQrAl9QzV.M1 
+0

我敢打赌,这不是crypt()问题,它只是Windows:P如果在其他非Windows操作系统(如RedHat,Solaris和Debian)中使用相同的参数,会发生什么? – Juan

1

我有同样的问题,地下室......我有2台服务器的登录检查工作,但是当我将其转移到最新的服务器上时,它最终会停止工作。我绕着它走用MD5加密如下: 在register.php

$encrypted = md5($_POST["pass"]); 
... 

然后在login.php中

$password = md5($_POST["password"]); 
if ($password == $row["hash"]) 
     { 
      // remember that user's now logged in by storing user's details in session 
      $_SESSION["id"] = $row["id"]; 
      $_SESSION['username'] = $_POST['username']; 
      $_SESSION['logged'] = 'Yes'; 
      // redirect to homepage 
      redirect("index.php"); 
     } 

我希望帮助:)