目錄
一、CSRF Token
二、代碼審計(High級別)
1、滲透準備
2、源碼分析
三、滲透實戰
1、滲透準備
2、修改URL重放失敗
3、burpsuite嘗試重放失敗
4、安裝CSRF Token Tracker
5、安裝logger插件
6、配置CSRF Token Tracker
7、bp再次重放報文
8、查看CSRF Token Tracker效果
本系列為通過《DVWA靶場通關筆記》的CSRF關卡(low,medium,high,impossible共4關)滲透集合,通過對相應關卡源碼的代碼審計找到講解滲透原理并進行滲透實踐,本文為跨站請求偽造CSRF High關卡的滲透部分。
一、CSRF Token
CSRF(Cross-Site Request Forgery,跨站請求偽造)Token 是一種安全機制,用于防止惡意網站利用用戶已認證的會話來執行未經授權的操作,核心原理如下所示。
-
服務器為每個會話或表單生成唯一的隨機令牌(Token)。
-
令牌嵌入表單或HTTP請求頭中。
-
服務器在處理請求時驗證令牌的有效性。
-
令牌通常是一次性的或有時效性。
即使攻擊者誘使用戶訪問惡意頁面,由于無法獲取有效Token,偽造的請求會被服務器拒絕。這種機制有效阻斷了CSRF攻擊鏈,是目前最可靠的CSRF防護方案之一。
二、代碼審計(High級別)
1、滲透準備
配置security為中等High級別,如下圖所示。
進入到CSRF關卡High頁面,發現這是一個修改密碼的頁面,與Low關卡相似,沒有確認舊密碼的輸入框,只有新密碼和確認新密碼的輸入框,具體如下所示。
http://127.0.0.1/DVWA/vulnerabilities/csrf/
2、源碼分析
進入DVWA靶場源目錄,找到High.php源碼,如下所示。
打開源碼High.php,分析可知這段代碼實現了一個不安全的密碼修改功能:該代碼實現了用戶密碼修改的功能。當檢測到Change參數存在時,先驗證防 CSRF 令牌的有效性。若令牌驗證通過,獲取用戶輸入的新密碼和確認密碼,檢查兩者是否匹配。若匹配,對新密碼進行轉義及哈希處理,構建 SQL 語句更新數據庫中當前用戶的密碼,并向用戶反饋密碼修改成功;若不匹配,則反饋密碼不一致的信息。最后關閉數據庫連接,并生成新的防 CSRF 令牌。它通過以下步驟實現:
- 檢查請求參數:通過 isset($_GET['Change']) 檢查是否存在名為 Change 的 GET 參數,以確定是否處理密碼更改請求。
- 驗證 Anti-CSRF 令牌:調用 checkToken 函數,驗證用戶提交的 CSRF 令牌是否與會話中的令牌一致,防止 CSRF 攻擊。
- 獲取用戶輸入:從 $_GET 中獲取用戶輸入的新密碼和確認密碼。
- 驗證密碼一致性:檢查新密碼和確認密碼是否一致。
- 轉義和加密密碼:對新密碼進行轉義處理,防止 SQL 注入,然后使用 MD5 加密。
- 更新數據庫:將加密后的密碼更新到數據庫中。
- 反饋用戶:根據操作結果,給用戶相應的提示信息。
- 生成新的 CSRF 令牌:調用 generateSessionToken 函數,生成新的 CSRF 令牌,用于后續的表單提交。
本關卡相對于low級別增加了token驗證,相對于medium級別則是缺少refer字段校驗但是增加了token驗證。CSRF 令牌驗證是指使用checkToken函數驗證請求中的user_token與會話中的session_token是否匹配。這要求攻擊者必須獲取用戶的有效令牌,而這在跨站請求中是無法實現的。本關卡也實現了令牌刷新機制,在每次請求后調用generateSessionToken()生成新的令牌,確保每個令牌只能使用一次,增強了安全性。詳細注釋后的代碼如下所示。
<?php
if( isset( $_GET[ 'Change' ] ) ) {// 檢查Change參數是否存在,確認用戶提交了密碼修改請求// 驗證CSRF令牌:檢查請求中的user_token與會話中的session_token是否匹配// 第三個參數是驗證失敗時的跳轉頁面checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// 從GET參數獲取新密碼和確認密碼$pass_new = $_GET[ 'password_new' ];$pass_conf = $_GET[ 'password_conf' ];// 驗證兩次輸入的密碼是否一致if( $pass_new == $pass_conf ) {// 密碼匹配,準備更新數據庫// 使用mysqli_real_escape_string防止SQL注入// 注意:此函數僅對字符串中的特殊字符進行轉義$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));// 使用md5哈希密碼(注意:md5已不安全,建議使用更安全的哈希算法如password_hash)$pass_new = md5( $pass_new );// 構建SQL查詢更新用戶密碼// dvwaCurrentUser()函數獲取當前用戶名$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";// 執行SQL查詢并處理可能的錯誤$result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );// 顯示密碼修改成功的消息$html .= "<pre>Password Changed.</pre>";}else {// 密碼不匹配,顯示錯誤消息$html .= "<pre>Passwords did not match.</pre>";}// 關閉數據庫連接((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
// 生成新的CSRF令牌并存儲在會話中
// 用于下次請求時驗證
generateSessionToken();
?>
三、滲透實戰
1、滲透準備
進入DVWA靶場的CSRF關卡High級別,將密碼改為admin,如下所示。
bp開啟攔截功能,點擊change后,頁面URL變為如下所示,包含剛剛修改的密碼和確認密碼值,還包含了一個新的參數token值,這與我們之前代碼分析一致,本關卡還會驗證token值。
http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=mooyuan&password_conf=mooyuan&Change=Change&user_token=a6257416ef53bed0a1d1ad062a1d0465#
同時頁面信息也發生改變提示修改密碼成功(Password changed),如下圖紅框所示。
bp攔截報文后,在http history中找到這個報文,計劃右鍵將報文發送到repeater模塊,具體的效果如下所示。
將報文發送到repeater模塊,嘗試是否可以進行CSRF攻擊偽造,具體效果如下所示。
2、修改URL重放失敗
修改URL參數的密碼,將新密碼和確認密碼均修改為000000,完整的URL如下所示。
http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=000000&password_conf=000000&Change=Change&user_token=a6257416ef53bed0a1d1ad062a1d0465#
將URL輸入到hackbar的地址欄中并點擊執行后修改密碼失敗,提示“CSRF token is incorrect”,如下所示。
這是因為使用token驗證后,此時token發生變化校驗token失敗導致。
3、burpsuite嘗試重放失敗
由于在地址欄直接修改失敗,我們使用bp的CSRF token Tracer來嘗試滲透。為了對比CSRF token Tracer的效果,首先展示沒有使用CSRF token Tracer的情況下修改密碼效果。
在第一步的bp repeater中修改密碼,將GET參數中的新密碼和確認密碼均修改為000000,修改后GET部分內容如下所示。
GET /dvwa/vulnerabilities/csrf/?password_new=000000&password_conf=000000&Change=Change&user_token=a6257416ef53bed0a1d1ad062a1d0465 HTTP/1.1
如下所示,這次http返回的狀態值為302,HTTP/1.1 302 Moved Temporarily。故而點擊follow redirection如下圖左上角的紅框所示。
點擊follow redirection后,重定向返回結果為CSRF token is incorrect,具體如下所示。
4、安裝CSRF Token Tracker
在 Burp Suite 的 BApp Store 中直接安裝 CSRF Token Tracker 插件,如下所示。
CSRF Token Tracker 是一款用于滲透測試的 Burp Suite 插件,主要用于自動獲取和更新 CSRF Token,從而繞過網站的 CSRF 防護機制。CSRF Token 是一種常見的防御機制,通過在每個請求中添加一個唯一的令牌來驗證請求的合法性。CSRF Token Tracker的主要功能如下所示。
- 自動獲取 CSRF Token:插件能夠自動從服務器響應中提取 CSRF Token,并將其添加到后續的請求中。
- 自動更新 Token:在多次請求中,Token 會自動更新,確保每次請求都使用最新的 Token。
- 繞過 CSRF 防護:通過自動處理 Token,該插件可以幫助測試人員繞過網站的 CSRF 防護,進行諸如暴力破解、數據包重放等測試。
5、安裝logger插件
Logger++ 是 Burp Suite 中一款功能強大的日志記錄和分析插件,提供了比 Burp 自帶日志更強大的記錄、過濾和搜索功能,可以記錄所有經過 Burp 的 HTTP/HTTPS 流量,為查看repeater修改密碼后的報文,安裝logger插件,效果如下所示。
6、配置CSRF Token Tracker
當前訪問host為127.0.0.1,token參數名為user_token,把包中的user_token值復制到CSRF Token Tracker中實現自動識別token值。特別注意 sync requests based on the following rules部分的勾要選上,如下所示。
7、bp再次重放報文
再次重放3.3部分的報文,為確保是csrf-token tracer自動獲取到token值,配置完成后,第一次重放需要點擊兩次send,第二次即可修改成功。在Logger中找到這個報文,查看token如下所示。
8、查看CSRF Token Tracker效果
查看CSRF Token Tracker自動識別到的user_token值,之后每次提交的重放都會自動識別并填充token值來實現繞過的目的。如下所示,user_token 已經更改為最新的token值。