1. 程式人生 > 實用技巧 >Dvwa教程之跨站偽造請求(三)

Dvwa教程之跨站偽造請求(三)

Low CSRF Source

<?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); }

可以看到,伺服器收到修改密碼的請求後,會檢查引數password_newpassword_conf是否相同,如果相同,就會修改密碼,並沒有任何的防CSRF機制

直接利用

http://192.168.0.115/dvwa-master/vulnerabilities/csrf/?password_new=aaa&password_conf=aaa&Change=Change#

誘導受害者直接點選這個連線就可以修改密碼

Medium CSRF Source

 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 ?>

Medium 級別的程式碼加入了來源檢查

設定了來源檢查

用burp檢視資料包

多了一個欄位Referer, 服務端程式碼中會去對比這個欄位判斷一下來源,

可以直接在burp直接新增這個欄位就可以修改成功

High CSRF Source

<?php

if( isset( $_GET[ 'Change' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // 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);
}

// Generate Anti-CSRF token
generateSessionToken();

?>

可以看到,High級別的程式碼加入了Anti-CSRF token機制,使用者每次訪問改密頁面時,伺服器會返回一個隨機的token,向伺服器發起請求時,需要提交token引數,而伺服器在收到請求時,會優先檢查token,只有token正確,才會處理客戶端的請求。
漏洞利用 由於跨域是不能實現的,所以我們要將攻擊程式碼注入到目標伺服器localhost中,才有可能完成攻擊。所以單純從CSRF未能突破High級別。

Impossible CSRF Source

可以看到,Impossible級別的程式碼利用PDO技術防禦SQL注入,至於防護CSRF,則要求使用者輸入原始密碼(簡單粗暴),攻擊者在不知道原始密碼的情況下,無論如何都無法進行CSRF攻擊。