2015-09-11 27 views
2

到現在爲止,我一直在使用md5和sha1加密我的PHP登錄密碼,但由於這些算法現在被認爲已過時並且不再安全,我想要構建一個新的登錄系統PHP函數password_hashpassword_verify。然而,有一件事我找不到解決這些功能的方法:爲了避免重放攻擊的安全性,僅僅爲每個密碼設置單獨的鹽是不夠的。因爲如果攻擊者以某種方式竊聽客戶端和服務器之間的通信,他可以將用戶名和已加密的密碼散列發送到服務器,就像原始客戶端一樣。所以我的解決方案一直是創建一個額外的「鹽」(我不知道是否有官方稱謂),只對一次登錄嘗試有效。因此,客戶端從服務器獲取兩種鹽(每個用戶帳戶總是相同的,每次用戶帳戶都是相同的),加密用戶輸入的密碼並將散列發送到服務器。然後服務器檢查這個散列(例如$ Hash == sha1($ HashFromDbWithFixedSalt。$ RandomHash))。然後創建一個新的$ RandomHash。因此,即使攻擊者模仿用戶的通信,他也無法獲得不允許的訪問權限。安全的PHP登錄對重播攻擊

新的PHP函數確實支持salt,但是我找不到一種方法來實現我的舊解決方案,因爲數據庫中的哈希將包含固定哈希(每個用戶帳戶不同),但不包含隨機哈希(僅適用於一次嘗試)。有沒有人有想法或者可能已經解決了這個問題?

編輯:

這是我用來做什麼的:

新用戶註冊:

  1. 請爲該用戶創建一個隨機鹽。
  2. 將md5($ password_in_cleartext + $ salt)和鹽本身保存到數據庫。

用戶想要登錄:

  1. 用戶發送他的用戶名與服務器
  2. 服務器從數據庫中查找他的鹽和創建,它在節省額外的隨機鹽$ _SESSION。它將這兩種鹽發送給用戶。
  3. 用戶在客戶端(通過JS)加密他的密碼,如下所示:sha1(md5($ password_in_cleartext + $ salt_from_the_db)+ $ random_salt)。他將這個散列發送給服務器。
  4. 服務器檢查sha1($ hash_from_the_db + $ random_salt)== $ hash_the_user_sent。如果不相等,則創建一個新的random_salt並將其發送給用戶(返回步驟3)。
+2

最好的方法是SSL,就像@samlev說的! – MozzieMD

+2

在客戶端上散列密碼不是加密。如果有的話,它可以減少安全性,因爲它減少了攻擊者可能的搜索空間。使用SSL來保護客戶端和服務器之間的通信(即*是*加密),然後使用諸如BCrypt之類的東西來散列它們的原始密碼。 – samlev

+0

另一個注意事項:在bcrypt中,salt是哈希密碼*的一部分。我知道這聽起來不太安全,但事實並非如此。 – samlev

回答

4

如果您不使用SSL,那麼您的登錄將不安全。不管你使用的哈希算法有多麼不可逆轉,有太多的其他方式來破壞交互。

而不是你的散列的大小,它與你做什麼有關。使用md5寫得好的系統比使用sha2的系統寫得更好。

假設您已經使用SSL和HSTS進行預註冊,並且使用了一些可緩存的ssl-stripping敏感的CSS,但仍需要更高的安全性,或者您在遠程SSL終止的共享服務器上運行,那麼您當前的方法是有效的,你只需要升級你的散列算法(以及分配用於存儲散列密碼的空間)。但是,正如你發現的,你仍然需要在應用會話salt hash之前回復存儲salt + password hash(提示:session id是後者的一個很好的熵源,但是session的值不應該被JavaScript訪問 - 生成一個會話ID服務器用作會話salt)。問題就變成了JavaScript中可用的哈希函數。

+0

很酷,謝謝你,這很有趣!所以我會使用password_hash(),或者甚至是隱含的crypt()函數,而不是使用password_verify()來驗證密碼,而是像以前那樣手動比較哈希值(其中一個是來自數據庫+會話的哈希值)鹽和客戶端上的JavaScript生成的另一個)? –

+0

Crypt只知道一層散列 - 使用存儲的鹽。所以你不能用它來驗證已經被哈希了兩次的密碼。 – symcbean

+0

當然,我可以;-)。我的PHP後端和客戶端都知道這兩種鹽。因此,客戶端首先使用存儲salt對密碼進行哈希處理。得到的散列與數據庫中的散列完全相同。然後,它再次使用會話salt對散列進行散列。然後PHP後端使用會話salt從db中散列散列。 Violà,如果用戶輸入正確的密碼,則兩個結果散列應該完全相同。 –

4

password_hash將自動爲每個密碼生成一個鹽。

散列密碼不應該傳回給用戶或離開服務器。如果您擔心流量嗅探,或者MITM attacks,請使用SSL/https。

這聽起來像你也試圖抵禦CSRF攻擊。在這種情況下,當用戶首次訪問頁面時,您會設置一個隨機標記,並期望它隨每個請求一起發送(這將停止無權訪問標記的站點代表發送請求用戶)。

+0

謝謝您的回答,但這並不是我的意思。我編輯了我原來的帖子,希望這會有幫助;-)。哦,我不想使用SSL,因爲它會花費額外的錢,我相信還有另一種方式。 –

+1

@ DennisP。它可能不是你想要的,但它是你想要的。除非你真的知道自己在做什麼,否則不要試圖發明自己的安全協議,最終會讓它變得更弱。 – Eborbob

+0

SSL不是[昂貴](https://www.ssls.com/)。你想要保護@DennisP的是什麼?有*沒有其他方式*。 –