密碼重置功能是一些常見漏洞的起因。例如用戶名枚舉漏洞(數據庫中用戶名不存在和密碼錯誤顯示不同的錯誤信息),敏感信息泄露(把明文密碼通過e-mail發送給用戶)重置密碼消息劫持(***會者接收到密碼重置信息)這些都是在密碼重置功能中比較常見的漏洞。
很多開發者都不能真正瞭解密碼重置所能引發的危害,而這個博客文章告訴大家一些不遵守基本安全準則的開發人員所開發的密碼重置功能會帶來哪些危害。
舉個例子,一個健壯的密碼恢重置功能會生成一個令牌,並通過電子郵件發送一個包含令牌的重置密碼連接給用戶。
令牌應具有以下特徵:
包含64個字符或者更多唯一性隨機性一次性擁有較短壽命(比如在24小時內到期)
當用戶點擊該鏈接時,應用程序必須檢查令牌是否有效。
如果令牌有效,應用程序必須註銷這個令牌,以便它不能被重用,並允許用戶更改自己的密碼。
此外,如果用戶試圖第二次重置密碼,在完成第一次重置過程之前,應用程序必須廢止舊的密碼重置請求並生成一個新的重置請求。
爲了提高安全性,也可以使用雙重的用戶身份認證(但並不是必須使用)。
比如,要求用戶回答之前填寫的隱私問題(比如我的大姨媽的名字是神馬)或確認發送到用戶手機的驗證碼。
現在,讓我們分析一個真實的並且設計的很糟糕的密碼恢復系統,列舉出所有相關的安全漏洞,並嘗試編寫POC
<?php
2:
3: /* generates a new random password */
4: function generatePassword() {
5: $chars = array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9");
6: for ($i = 0; $i < 10; $i++){
7: $password .= $chars[rand(0,35)];
8: }
9: return $password;
10: }
11:
12: /* send the new password to the user e-mail and update the database */
13: if ($_REQUEST['mail']) {
14: $con = new Connection();
15: $con->sql = " SELECT usr_user.id,
16: usr_user.name,
17: usr_user.email,
18: usr_user.password
19: FROM usr_user
20: WHERE usr_user.email = '" . $_REQUEST['mail'] . "'
21: ORDER BY id DESC ";
22: $res = $con->executeQuery();
23: if (is_array($res)){
24: $usr = $res[0];
25: $password = generatePassword();
26: $con->sql = "UPDATE usr_user SET password = MD5(trim('".$password."')) WHERE email = '" . $_REQUEST['mail'] . "' ";
27: $con->executeQuery();
28:
29: /* headers */
30: $headers = "MIME-Version: 1.0\r\n";
31: $headers .= "Content-type: text/html; charset=iso-8859-1\r\n";
32:
33: /* aditional headers */
34: $headers .= "To: " . $usr->name . " <" .="" 35:="" headers="" 36:="" 37:="" message="" body="" 38:="" html="" 39:="" usr-="">name . '';
40: $html .= '';
41: $html .= '';
42: $html .= '
';
43: $html .= '';
44:
45: /* Send e-mail to user with his new password
46: if (mail($_REQUEST['mail'], "Your new administrative password", $html, $headers)){
47: $message = "Your new password was sent to: " . $_REQUEST['mail'];
48: $success = true;
49: }
50: } else {
51: $message = "The provided e-mail is invalid";
52: $success = false;
53: }
54:
55: }
56:
57: ?>
(1)用戶名枚舉
最明顯的漏洞就是用戶名枚舉漏洞,用戶提交一個郵箱地址,如果郵箱存在那麼,系統會返回一條信息
"Your new password has been sent to: [email protected]"
如果該郵箱沒有被人註冊,那麼系統將返回
"The provided e-mail is invalid"
(2)拒絕服務
第二個漏洞應該是拒絕服務
這個系統中有一個生成隨機密碼的函數,***者可以編寫一個腳本來不斷嘗試重置密碼過程(原文中給出15秒每次,懷疑頻率是否有點低)
另外,如果配合用戶名枚舉漏洞的話,這個漏洞會產生更大的危害,可以用來更改任意用戶的密碼。(雖然你收不到該密碼,但也可以給用戶產生不小的麻煩)
(3)敏感信息泄露
第三個漏洞是敏感信息泄露,因爲該系統使用明文把密碼通過郵件發送給用戶,並且沒有在用戶下次登錄的時候
強制用戶修改密碼。如果***者獲取了用戶的郵件信息(其實這個也不算特別容易),就可以通過郵件中的密碼登錄系統。
(4)SQL 注入
第四個注入漏洞也比較明顯,用戶提交的數據沒有經過過濾直接代入查詢語句,利用方式也有很多種。這樣構造可以改掉所有用戶的密碼,也可以用來造成拒絕服務***。
Input: ’ or 1=1%23First SQL becomes (Line 15): SELECT usr_user.id, usr_user.name, usr_user.email, usr_user.password FROM usr_user WHERE usr_user.email = ’’ or 1=1#’ ORDER BY id DESCSecond SQL becomes (Line 26): UPDATE usr_user SET password = MD5(trim(‘xxxxxxxxxx’)) WHERE email like ’’ or 1=1#’
這個注入點還可以用來進行盲注來猜測一些敏感信息。
(5)跨站腳本漏洞
第五個漏洞也可以很明顯的找到,用戶輸入的mail參數被帶入到了郵件內容中(沒有經過任何過濾),這個漏洞的利用需要配合
SQL 注入漏洞來使用
User Input: ’ or 1=1%23<script>alert(1)</script>First SQL becomes (Line 15): SELECT usr_user.id, usr_user.name, usr_user.email, usr_user.password FROM usr_user WHERE usr_user.email = ’’ or 1=1#<script>alert(1)</script>‘ ORDER BY id DESCSecond SQL becomes (Line 26): UPDATE usr_user SET password = MD5(trim(‘xxxxxxxxxx’)) WHERE email like ’’ or 1=1#<script>alert(1)</script>‘Response Message (Line 47): Your new password was sent to: ’ or 1=1#<script>alert(1)</script>
提交上述數據,系統首先會修改所有用戶的密碼,然後給所有用戶發送包含惡意腳本的文件
(6)密碼重置信息劫持
最後一個漏洞是密碼重置信息劫持,也是危害比較嚴重的漏洞。產生原因是,用戶提交數據mail(又是這貨)被包含到了MIME頭中,這個漏洞的利用同樣需要配合SQL注入:
User Input: [email protected]%00’ or 1=1%23First SQL becomes (Line 15): SELECT usr_user.id, usr_user.name, usr_user.email, usr_user.password FROM usr_user WHERE usr_user.email = ’[email protected][null byte char]’ or 1=1#’ ORDER BY id DESC Second SQL becomes (Line 26): UPDATE usr_user SET password = MD5(trim(‘xxxxxxxxxx’)) WHERE email like ’[email protected][null byte char]’ or 1=1#’MIME Header becomes (Line 34): To: John Smith <LanLan@wyl.com[nullbytechar]’ or 1=1#>
執行上面的代碼的結果就是所用用戶密碼被修改,修改後的郵件會被髮送到[email protected],這裏[null byte char]會截斷mini頭中的信息