DVWA-SQL Injection (Bind) SQL盲注

盲注同于union select查询注入,盲注只能得到数据库回显的正确和错误,利用返回的正确和错误一个一个判断。

LOW

审计源码

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    // 获取 id 
    $id = $_GET[ 'id' ];
    // 定义存在为 false
    $exists = false;
    // 判断数据库类型
    switch ($_DVWA['SQLI_DB']) {
        // MYSQL数据库
        case MYSQL:
            // 数据库查询
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ); // Removed 'or die' to suppress mysql errors
            // 定义存在还是 false
            $exists = false;
            // 判断数据库查询是否有结果
            if ($result !== false) {
                try {
                    // 获取返回结果中的函数
                    $exists = (mysqli_num_rows( $result ) > 0);
                } catch(Exception $e) {
                    // 没有结果定义为 false
                    $exists = false;
                }
            }
            ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
            break;
        case SQLITE:
            global $sqlite_db_connection;

            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
            try {
                $results = $sqlite_db_connection->query($query);
                $row = $results->fetchArray();
                $exists = $row !== false;
            } catch(Exception $e) {
                $exists = false;
            }

            break;
    }
    // 判断数据库是否查询成功
    if ($exists) {
        // 查询成功
        echo '<pre>User ID exists in the database.</pre>';
    } else {
        // 找不到用户
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // 插叙失败
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

}

?>

根据查询结果,只返回了查询正确和错误两种结果,对传入的id没有进行过滤,所以可以直接进行注入
通过观察在$id左右加入了'',所以这是一个字符型的注入
SQL盲注非常的繁琐
普通的注入为发现注入点 -> 判断注入类型 -> 获取当前数据库的名 -> 获取当前数据库中表明 -> 获取表中的字段名 -> 获取字段内容
盲注
1.判断注入类型 -> 2.获取当前数据库名:获取当前数据库的长度,获取当前数据库的第一个字符的ascii码值,获取当前数据库的第二个字符的ascii码值........ -> 3.获取当前数据库中的表名: 获取当前数据库中表的数量,获取第一个表名长度,获取第一个表名的第一个字符的ascii码值........ -> 4.获取第一个表中的字段名: 获取第一个表中字段的数量,获取第一个字段的长度,获第一个字段的第一个字符的ascii码值........ -> 5.依次类推
这里的绕过方法为1'#,详细步骤可以到另一篇博客
Less-5 和 Less-6 SQL盲注
这里也可以写一个sql盲注的脚本,后续补出来

Medium

审计源码

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // 获取 id
    $id = $_POST[ 'id' ];
    $exists = false;
    // 判断数据库类型
    switch ($_DVWA['SQLI_DB']) {
        // mysql数据库
        case MYSQL:
            // mysqli_real_escape_string 传入 id 进行实例化
            $id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

            // 执行SQL语句
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ); // Removed 'or die' to suppress mysql errors

            $exists = false;
            // 判断是否成功执行 SQl 语句
            if ($result !== false) {
                try {
                    // 获取执行 SQL 返回的行数
                    $exists = (mysqli_num_rows( $result ) > 0); // The '@' character suppresses errors
                } catch(Exception $e) {
                    $exists = false;
                }
            }
            
            break;
        case SQLITE:
            global $sqlite_db_connection;
            
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
            try {
                $results = $sqlite_db_connection->query($query);
                $row = $results->fetchArray();
                $exists = $row !== false;
            } catch(Exception $e) {
                $exists = false;
            }
            break;
    }
    // 判断数据库查询是否返回结果
    if ($exists) {
        // 返回结果
        echo '<pre>User ID exists in the database.</pre>';
    } else {
        // 没有返回结果
        echo '<pre>User ID is MISSING from the database.</pre>';
    }
}

?>

使用POST方式传参id并使用mysqli_real_escape_string进行了实例化操作,但是这题是数字型的SQL注入,所对我们注入没什么影响
不用使用闭合,使用hackbar直接进行传参
payload:Submit=Submit&id=1 and length(database()) > 0 %23
判断当前数据库的长度是否大于 0

可以看到返回正确,这样一步结果就出来了

High

审计源码

<?php

if( isset( $_COOKIE[ 'id' ] ) ) {
    // 获取传入的 id
    $id = $_COOKIE[ 'id' ];
    $exists = false;

    // 判断数据库类型
    switch ($_DVWA['SQLI_DB']) {
        case MYSQL:
            // 进行数据库查询,后面的和Low基本一致
            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
            $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ); // Removed 'or die' to suppress mysql errors

            $exists = false;
            if ($result !== false) {
                // Get results
                try {
                    $exists = (mysqli_num_rows( $result ) > 0); // The '@' character suppresses errors
                } catch(Exception $e) {
                    $exists = false;
                }
            }

            ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
            break;
        case SQLITE:
            global $sqlite_db_connection;

            $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
            try {
                $results = $sqlite_db_connection->query($query);
                $row = $results->fetchArray();
                $exists = $row !== false;
            } catch(Exception $e) {
                $exists = false;
            }

            break;
    }

    if ($exists) {
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
        // Might sleep a random amount
        if( rand( 0, 5 ) == 3 ) {
            sleep( rand( 2, 4 ) );
        }

        // User wasn't found, so the page wasn't!
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }
}

?>

通过观察High的源码,除了获取id的方式和LOW级别不一样,其余都类似
使用1'#依然可以绕过

Impossible

审计源码

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    // 检查user_token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    $exists = false;

    // 获取传入的id
    $id = $_GET[ 'id' ];

    // 查看 id 是否为数字
    if(is_numeric( $id )) {
        // 将 id 转换为字符串
        $id = intval ($id);
        // 判断数据库类型
        switch ($_DVWA['SQLI_DB']) {
            // mysql
            case MYSQL:
                // 使用 PDO 方法进行sql查询
                $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
                $data->bindParam( ':id', $id, PDO::PARAM_INT );
                $data->execute();

                $exists = $data->rowCount();
                break;
            case SQLITE:
                global $sqlite_db_connection;

                $stmt = $sqlite_db_connection->prepare('SELECT COUNT(first_name) AS numrows FROM users WHERE user_id = :id LIMIT 1;' );
                $stmt->bindValue(':id',$id,SQLITE3_INTEGER);
                $result = $stmt->execute();
                $result->finalize();
                if ($result !== false) {
                    // There is no way to get the number of rows returned
                    // This checks the number of columns (not rows) just
                    // as a precaution, but it won't stop someone dumping
                    // multiple rows and viewing them one at a time.

                    $num_columns = $result->numColumns();
                    if ($num_columns == 1) {
                        $row = $result->fetchArray();

                        $numrows = $row[ 'numrows' ];
                        $exists = ($numrows == 1);
                    }
                }
                break;
        }

    }

    // Get results
    if ($exists) {
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    } else {
        // User wasn't found, so the page wasn't!
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?>

后面大概的我也没有看,首先判断是否为数字,然后类型转换为字符串类型,之后又使用PDO方法方法SQL注入,和普通的SQL注入一样的防御方法

posted @ 2022-05-31 11:49  Junglezt  阅读(122)  评论(0编辑  收藏  举报