2011-03-10 53 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"); 
     } 

我希望幫助:)