LOW:
先嘗試change一組密碼:123456
修改成功,我們觀察上面的url代碼
http://localhost/DVWA/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change#
將password_new部分與password_conf部分改成我們想要的密碼:4321
http://localhost/DVWA/vulnerabilities/csrf/?password_new=4321&password_conf=4321&Change=Change#
新建一個頁面打開,發現密碼修改成功
?MEDIUM:
嘗試同樣的方法發現請求失敗
并且上方跳出來這個?,第一行說請求頭缺失,請求頭記錄著
查看這一關的源碼并與low的做對比 ,多出來的這個if判斷條件應該是判斷當前的訪問請求是否更換頁面了,如果不是,就不執行請求
用bp抓包原來的請求,可以注意到這里有一個referer
***Referer***:
是http請求頭中的一個字段,作用是指示當前請求的網頁的來源,也就是說,?referer后面的內容會告訴服務器這個請求來自于哪個頁面或者url
在url里面像low一樣修改成我們想要的密碼,新起一個頁面,bp抓包,抓到這些
send to repeater,添加如下代碼
Referer:localhost
render!修改成功!!!
HIGH:
我們剛才改的密碼是1111,這一級我們要把它改成0000
先提交一個新密碼hhhh,并且bp抓包,抓到這些,發現這一關有了token驗證
send to intreuder,和第一關一樣,先clear,再把三個參數add進去,攻擊方式選擇Pithchfork
然后去Payloads,在payloas setting里add進我們要修改的密碼,防止token失效,我們多加幾組
然后和第一關一樣,遞歸找token,先在資源池resoource pool里設置單線程
?settings里(有的版本的dp是options)
回payloads,加上
Start attack!!!!!!!!!!
關閉bp,去第一關,輸入用戶名和密碼
登陸成功!!!!!!!!!
IMPOSSIBLE:
?我們觀察一下源碼
CSRF Source
vulnerabilities/csrf/source/impossible.php<?phpif( isset( $_GET[ 'Change' ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// Get input$pass_curr = $_GET[ 'password_current' ];$pass_new = $_GET[ 'password_new' ];$pass_conf = $_GET[ 'password_conf' ];// Sanitise current password input$pass_curr = stripslashes( $pass_curr );$pass_curr = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_curr ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));$pass_curr = md5( $pass_curr );// Check that the current password is correct$data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );$data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );$data->execute();// Do both new passwords match and does the current password match the user?if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) {// It does!$pass_new = stripslashes( $pass_new );$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)) ? "" : ""));$pass_new = md5( $pass_new );// Update database with new password$data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );$data->bindParam( ':password', $pass_new, PDO::PARAM_STR );$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );$data->execute();// Feedback for the userecho "<pre>Password Changed.</pre>";}else {// Issue with passwords matchingecho "<pre>Passwords did not match or current password incorrect.</pre>";}
}// Generate Anti-CSRF token
generateSessionToken();?>
優化地方:
- 使用了pdo預處理:我的理解是提前規劃好了傳遞數據的模板,只從用戶的輸入中提取數據,而其輸入不能當成代碼處理,比如 'or '1'=1,只能被當初密碼
- checktoken
- mysqli_real_escape_string 轉義
- 原密碼驗證,攻擊者很難知道
- MD5加密,好像需要彩虹表解密,還不了解
綜上,無法突破