網站是如何記住你的密碼的?

最近 , 國內知名安全團隊烏云漏洞平臺曝出了網易郵箱所遭到的一次大范圍攻擊 , 稱上億用戶的賬號密碼以及安全提示問題和答案被泄露 , 同時有很多用戶稱自己的Apple ID等賬號遭到竊取 , 密碼被改 , iPhone手機被鎖定并遭到敲詐 , 而這些用戶都是將網易郵箱作為Apple ID來使用的 。 在此之前 , 也有一些網站出過類似的安全事故 , 而即便有了如此多的教訓 , 很多網站在保存和管理用戶密碼這件事上依然做得十分糟糕 , 這成了信息安全的一個嚴重的短板 。
在一般的身份認證體系中 , 賬號(也就是ID)和密碼是配合使用的 , 也就是說 , 賬號用來識別這個用戶是誰 , 而密碼用來識別這個用戶是不是他本人 , 因為我們一般假定密碼只有用戶本人才知道 。 既然如此 , 那么網站必須要保存用戶的賬號和密碼才能完成身份確認 , 而一般來說 , 賬號和密碼是保存在網站后臺的數據庫系統中 , 比如說類似這樣一張表:

網站是如何記住你的密碼的?



這樣一來 , 當用戶輸入賬號user1 , 密碼123456時 , 網站就能從數據庫中找到相應的用戶 , 然后再檢查一下密碼對不對 , 密碼對了就登錄成功 。 不過 , 這種原原本本保存用戶密碼的方法其實很不安全 , 因為一旦攻擊者通過某種方式獲取了后臺數據庫的訪問權限 , 就能夠輕松地取得所有用戶的賬號和密碼 。 我們知道 , 人類的記憶力其實十分有限 , 大多數用戶在不同的網站上用的其實是同一套賬號和密碼 , 只要其中一個網站的賬號和密碼泄露出去 , 造成的后果是不堪設想的 , 因為攻擊者可以用這些信息碰運氣 , 說不定可以登錄其他很多網站 , 如果那些網站僅僅是論壇、社區、博客之類的還好 , 而如果是支付寶或者銀行呢?
實際上 , 如果時間倒回到十幾年前 , 恐怕大部分網站都是用這種方式來保存用戶的密碼的 , 想想就令人毛骨悚然呢 。 不過 , 業界對于安全的追求也并沒有懈怠 , 很快人們就發現這樣做實在不靠譜 , 于是開始想辦法進行改進 。 改進的思路其實也不難 , 既然密碼只是用來驗證對不對的 , 那么網站其實并不需要保存密碼本身 , 而是只要保存一個密碼的“指紋”就行了 。 這里的“指紋”用的是一種叫做“散列函數”(hash function)的算法 , 簡單來說 , 對于任意的信息 , 通過散列函數可以生成一段摘要 , 也叫散列值 , 散列值的長度是固定的 , 比如如果我們把123456輸入一個叫做MD5的散列函數 , 得到的散列值為:e10adc3949ba59abbe56e057f20f883e 。 散列函數有一個特點 , 那就是它是一種單向算法 , 也就是說 , 已知一段信息可以算出一個確定的散列值 , 但已知一個散列值卻無法算出原始信息 。 有了散列函數的幫助 , 網站可以像下面這樣保存密碼了:
網站是如何記住你的密碼的?



當用戶登錄時 , 比如說輸入賬號user1 , 密碼123456 , 網站先計算出123456的散列值 , 然后再與數據庫中保存的散列值進行對比 , 如果一樣就說明登錄成功了 。 那么疑問來了 , 如果用戶輸入的密碼不是123456 , 就一定不能得到和數據庫中保存的一樣的散列值嗎?事實上 , 散列函數是一種多對一的映射 , 因為信息的長度可以是任意的 , 但散列值永遠只有固定的長度 , 就像把100個球放進10個袋子里 , 必然有至少一個袋子里面得裝多于一個的球 , 換句話說 , 必然存在兩條不同的信息 , 它們的散列值恰好是一樣的 , 這種情況叫做散列碰撞 。 盡管對于散列函數來說 , 碰撞是必然存在的 , 但是一個好的散列函數可以讓碰撞足夠分散 , 使得攻擊者無法人為地制造出碰撞 , 不幸的是 , 我們上面提到的MD5就是一個不太好的散列函數 , 它的抗碰撞性已經很差了 , 或者說已經很不安全了 , 然而 , 根據烏云平臺的描述 , 網易郵箱依然在使用MD5來保存用戶的密碼 , 也是醉了吧?在常用的散列函數中 , MD5已經被淘汰 , SHA-1的安全性也較弱 , SHA-2是主流 , 而SHA-3則具備更高的安全性 。

猜你喜歡