大多數(shù)Web應用程序要求其用戶通過詢問用戶名和密碼來對自己進行身份驗證。他們將用戶提供的憑據(jù)與存儲在其數(shù)據(jù)庫中的數(shù)據(jù)進行比較,如果憑據(jù)匹配,則授予用戶訪問權限。聽起來不錯!但是,如果網(wǎng)站存儲密碼的數(shù)據(jù)庫遭到破壞,將會發(fā)生什么?本文介紹了在數(shù)據(jù)庫中存儲密碼的各種技術。
大多數(shù)網(wǎng)站中有55%的網(wǎng)絡用戶使用相同的密碼!這意味著,如果以純文本形式存儲您的密碼的網(wǎng)站遭到破壞,黑客不僅可以訪問該網(wǎng)站上的帳戶,還可以訪問您使用相同密碼的所有社交媒體,電子郵件,論壇等帳戶!
好吧,許多人一定想知道,如果數(shù)據(jù)庫暴露給黑客,那該怎么辦?黑客有權訪問所有信息。錯誤!有很多方法可以使黑客從數(shù)據(jù)庫中檢索密碼變得很麻煩。即使這樣,開發(fā)人員還是傾向于忽略基本準則,而是以純文本形式存儲密碼。有超過30%的網(wǎng)站以純文本形式存儲您的密碼(也包括一些知名網(wǎng)站)。如果網(wǎng)站以純文本形式存儲您的密碼,那么無論您選擇多強的密碼,都不安全!
在數(shù)據(jù)庫中存儲純文本密碼是一種罪過:可能還會有人認為,如果不是純文本,那么我們必須對密碼進行加密然后再存儲。這也是一個可怕的想法。加密功能提供輸入和輸出之間的一對一映射,并且它們始終是可逆的。如果黑客獲得了密鑰,他將能夠解密密碼。更好的方法是使用單向加密哈希函數(shù)。散列函數(shù)在輸入和輸出之間提供多對一映射,實際上不可能反轉輸出。好的加密哈希函數(shù)具有較少的沖突(即,對于函數(shù)的不同輸入值,很難獲得相同的輸出)。由于鴿洞原理,無法完全避免碰撞。對于哈希密碼,我們可以假設哈希函數(shù)將生成唯一的輸出,即對于沒有兩個不同的密碼,我們將獲得相同的哈希值。
一些流行的加密哈希函數(shù)是MD5和SHA1。代替將純文本密碼存儲在數(shù)據(jù)庫中,一種方法是存儲密碼的哈希。您可能會想,如果我們無法從哈希中找回實際密碼,那么我們將如何驗證用戶輸入的憑據(jù)?很簡單,對用戶輸入的密碼應用相同的哈希函數(shù),然后將其與數(shù)據(jù)庫中存儲的哈希進行比較。如果兩個哈希都匹配,則對用戶進行身份驗證(因為相同輸入的哈希將提供相同的輸出)。現(xiàn)在,如果攻擊者能夠訪問數(shù)據(jù)庫,則他將只能查看哈希輸出,而不能查看實際密碼。
使用加密哈希功能比存儲純文本密碼更好:黑客是聰明人,一旦他們知道開發(fā)人員正在存儲哈希密碼,便會預先計算大量單詞(從常用單詞列表或詞典單詞中)的哈希值。他們創(chuàng)建了一個單詞表及其相應的哈希表。該表被稱為Rainbow Table,可隨時在線獲得。他們可以使用此表通過比較從數(shù)據(jù)庫獲得的哈希值來反向查找實際密碼。因此,擁有一個強大的密碼非常重要,因為密碼出現(xiàn)在單詞列表中的可能性越來越小。
隨著GPU和CUDA,OpenCL庫的引入,處理能力大大提高??焖俚腉PU可以在一秒鐘內(nèi)生成數(shù)百萬個MD5/SHA1哈希。因此,黑客可以通過暴力破解各種可能的組合輕松地生成大量哈希,并將其與存儲在數(shù)據(jù)庫中的哈希進行比較以提取實際密碼。
甚至哈希密碼也不安全!驚訝嗎不要失去希望!開發(fā)人員仍然可以采取一些措施來防止您的密碼被黑客竊取。加入一些鹽使密碼更美味!鹽是隨機數(shù)據(jù),在將其作為哈希函數(shù)的輸入發(fā)送之前,已與您的密碼連接在一起。例如:如果您的密碼是abc,鹽是!ZaP0#8,則hashFunction('abc!ZaP0#8')的結果將存儲在數(shù)據(jù)庫中,而不是hashFunction('abc')。因此,彩虹表攻擊現(xiàn)在將不再有效,因為彩虹表包含“abc!ZaP0#8”散列的概率很?。ㄒ驗橥ǔ2屎绫硎怯沙S迷~,字典詞等構成的)。鹽不存儲在數(shù)據(jù)庫中,而僅存在于外部用戶無法訪問的應用程序配置文件中。獲得對源文件的訪問比獲得對數(shù)據(jù)庫的訪問困難。上述加鹽方法是靜態(tài)的。我們?yōu)樗忻艽a設置了一個固定的位數(shù)。要驗證用戶身份,請先將固定鹽連接到用戶提供的輸入(密碼),然后將值傳遞給哈希函數(shù),然后將其與數(shù)據(jù)庫中存儲的值進行比較。但是,這種方法仍然容易受到暴力攻擊,如果攻擊者能夠獲得靜態(tài)鹽,則可以通過將鹽串聯(lián)在每個單詞中來使用舊的攻擊方法。
更好的方法是使用動態(tài)鹽。對于每個用戶,加密強度高的隨機字符串生成器都會生成新的鹽。用戶輸入的密碼與隨機生成的鹽和靜態(tài)鹽串聯(lián)在一起。連接的字符串作為哈希函數(shù)的輸入傳遞。獲得的結果存儲在數(shù)據(jù)庫中。由于動態(tài)鹽對于不同用戶而言是不同的,因此需要將其存儲在數(shù)據(jù)庫中。當要驗證用戶身份時,首先從數(shù)據(jù)庫中獲取該用戶的動態(tài)鹽的值,然后將其與用戶提供的輸入和靜態(tài)鹽連接起來。將結果與存儲在數(shù)據(jù)庫中的哈希進行比較。
如果數(shù)據(jù)庫遭到入侵,黑客不僅會獲取您的密碼哈希,還會獲取所使用的動態(tài)鹽。您可能想知道,如果攻擊者擁有動態(tài)鹽,那么動態(tài)鹽比靜態(tài)鹽有什么優(yōu)勢?即使攻擊者擁有動態(tài)鹽,他也需要為數(shù)據(jù)庫中存在的每個用戶(根據(jù)動態(tài)鹽)創(chuàng)建一個新的哈希表(或Rainbow表)。這比為所有用戶只創(chuàng)建一張表要昂貴得多。