第一次聽說鹽值加密的時候,總是感覺怪怪的。因為總會聯想到咸,聯想到密碼是咸的。
其實這里所說的鹽,簡單的說,就是一組安全隨機數。它會在特定的時候,加入到密碼中(一般來說是加密后的密碼)。從而使密碼變得更有味道(從單一簡單化到復雜化),更安全。
下面我們就通過安全威脅分析分別說說當前兩種加鹽的形式:
一、數據庫泄露
眾所周知,用戶名和密碼是被保存在數據庫中。可是一旦數據庫發生了泄露,用戶名和密碼就都遭到了泄露。攻擊者可以輕松的獲取用戶名和密碼,進行操作。更大的危害是,由於現在需要注冊的網站、app越來越多。用戶名和密碼很多時候都是相同的。一旦某處發生了泄露,則后果會慢慢的擴散。這些危害大家可以查詢下近些年發生的一些安全事故,如Sony數據庫泄露、網易數據庫泄露、CSDN數據庫泄露等。
解決這個問題的通用方法是:
1、對密碼進行加密存儲
這樣的好處是,即使數據庫發生了泄露,攻擊者也不會拿到明文密碼,依然無法直接使用這些密碼。
但是這樣的存儲方式也存在缺點:很多用戶在注冊時都是使用的弱密碼。攻擊者可以通過大量的注冊用戶,這些用戶使用擴散的使用各種弱密碼。當拿到數據庫密文后,根據已知的用戶名密碼,就可以獲取到相關的彩虹表。然后依據彩虹表依次匹配數據庫中的密碼。這樣就可以得到其中使用弱(防盜連接:本文首發自http://www.cnblogs.com/jilodream/ )密碼的用戶了。同時app、web等軟件由於用戶體驗等原因,也不可能讓用戶設置安全系數過高的密碼。如8位以上、包含大小寫、特殊字符、於最近三次的密碼不能相同、於上次密碼至少有三位不同、不能包含密碼字典中涉及的簡單密碼等等。舉個例子:如ATM、微信支付密碼使用的是純6位數字,這樣就有了10^6種可能,攻擊者只要拿到了全套的密碼對應的彩虹表,就可以獲取到所有用戶的密碼。這套彩虹表,攻擊者可以通過使用大量的簡單密碼注冊用戶得到。然后從獲取到的數據庫中找到攻擊者自己注冊的這些用戶數據,進而拿到彩虹表。那么該怎么解決呢?這就涉及到固定鹽值加密。
2、對密碼進行加密
如前文所說,這個鹽是一個隨機數。當用戶注冊一個簡單密碼時,系統會同時生成這樣一個salt,於該用戶對應,保存到數據庫中。
這樣當用戶的密碼是888888時,后台真實存儲的密碼時888888鹽化以后的值。
操作步驟如下:
(1)注冊、修改密碼時,前台將 888888加密后的pwd1,傳入后台
(2)后台拿到pwd1以后,生成一個相應的隨機數 salt。將pwd1與salt拼接並再次加密,生成pwd2
(3)后台將pwd2和salt 一並存儲到數據庫中。
(1-)當用戶每次輸入用戶名密碼后,將密碼加密生成pwd1'后,傳入后台。
(2-)后台拿到pwd1'后,根據用戶名id拿到對應的鹽值。與鹽值拼接加密后,生成pwd2‘。
(3-)然后判斷pwd2'與數據庫中的pwd2是否一致即可。
這里有兩點需要注意:
1、密碼在前后台的加密方式可以采用不同的形式
2、鹽值的拼接不一定非要拼接到最后,也可以放在前邊、插在中間、甚至拆開或者倒序拼接。
3、(防盜連接:本文首發自http://www.cnblogs.com/jilodream/ )
這樣即使是簡單密碼也沒關系。因為相同的密碼在數據庫中存儲的值並不一樣。攻擊者無法構造有效的彩虹表進行破解。
(二)重放攻擊
先拋開前邊的固化鹽值加密不說,我們再說說另外一種攻擊方式:重放攻擊(Replay Attacks)又叫重播攻擊、回放攻擊或新鮮性攻擊(Freshness Attacks)。
這里舉個簡單的例子:當用戶A進行登錄后,前台會將加密后的密碼,以數據包的形式發送到服務端。服務端會進行鹽化等加密手段后,再進行安全校驗。可是如果這個數據包被攻擊者截獲。並且分析出數據包的結構(如哪些字段代表用戶名、哪些代表IP/會話ID),然后進行適當的修改,再次發送給服務端后,服務端依然會進行常規的校驗,依然會驗證通過。也就是說無論客戶端,服務端的加密手段多么的復雜,一旦攻擊者有能力截獲和修改前后台通信的數據包,那么這些攻擊都將不起作用。
那么如何防范呢?仔細想想重放攻擊,攻擊者利用的是每次發送的包(防盜連接:本文首發自http://www.cnblogs.com/jilodream/ )中用戶名密碼等部分不變的機理。
那么我們可以讓他改變,怎么改變呢?
大致思路如下:
(1-)每次登陸時,我們可以生成一個隨機數(一個動態生成的salt),這個salt在前后台各自保存一份。
(2-)當用戶名輸入完密碼pwd后。前台會進行 f1(pwd)加密,然后與動態生成的salt拼接,然后再次加密。
也就是 pwd1=f2(f1(pwd)+salt)。之后前台就把這個pwd1發送到后台。(注意由於動態salt每次都會改變,所以pwd1每次也會改變)
(3-)后台拿到數據后,如果沒有使用固化鹽值加密的話,直接將數據庫中的數據采用相同的方式與服務端保存的動態salt拼接加密然后再對比即可。
如果同時存在固化鹽值加密的話,需要想辦法剔除掉這個動態salt(即f2()使用可逆的機密算法),然后再拼接固化salt接着再次加密,最后與數據庫對比即可。