something about DVWA - SQL Injection(Blind)
DVWA
SQL Injection(Blind)(sql注入 盲注)
在SQL注入过程中并不会给客户端返回查询到的内容
。
用来对程序对应的数据存储区
进行对应的探测。
盲注分类
盲注主要有两种:基于时间
,基于布尔
的盲注。
基于时间的盲注
通过向SQL中注入
sleep(int x)
,观察响应时间是否有对应延迟,如果有,则数据是存储在数据库中。例如:
1
2
3`--`或`#` 用来注释掉注入点之后的语句。
select * from tableA A where A.colA = '1' # and A.colB = '2';
select * from tableA A where A.colA = '1' -- and A.colB = '2';1
2# 查询并等待5s
1' and sleep(5) #基于布尔的盲注
通过向SQL中注入
and 1=1
或and 1=2
,观察响应内容是否不同,如果不同,则数据是存储在数据库中。例如:
1
2# 注入true
1' 1=1 #1
2# 注入false
1' 1=2 #
Low
手动测试
在注入点注入基于时间的盲注
能够观察到有明显的延迟。
1
1' and sleep(5)#
在注入点注入基于布尔的盲注
能够观察到两种布尔值对应的回应不相同。
1
21' and 1=1#
1' and 1=2#
源码分析
直接从
request
中获取参数(GET)
1
2// Get input
$id = $_GET[ 'id' ];直接将参数拼接入SQL文中执行
1
2
3// Check database
$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根据查询结果返回对应页面
1
2
3
4
5
6
7
8
9if ($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>';
}
Medium
手动测试
使用
burpsuit
拦截后,与Low
级别相同。针对
mysqli_real_escape_string()
的制御,可以将注入内容url encode
,进行绕过。源码分析
直接从
request
中获取参数(POST)
1
2
3// Get input
$id = $_POST[ 'id' ];
$exists = false;将参数转义特殊字符后拼接入SQL执行
1
2
3
4
5
6// 使用`mysqli_real_escape_string()`函数转义特殊字符。
$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
$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根据查询结果返回对应页面
与
Low
级别相同。
High
burpsuit 测试
抓包,找到注入点
1
2
3
4
5
6
7
8
9
10
11
12GET /dvwa/vulnerabilities/sqli_blind/
Host: train.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://train.com/dvwa/security.php
Connection: close
Cookie: id=2; security=high; PHPSESSID=9jcja8m0r7k7h2je6ife9ivmaj
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache针对
Cookie: id=$2$
注入与
Low
级别相同,可得盲注结果。
源码分析
从
cookie
中获取参数1
2
3// Get input
$id = $_COOKIE[ 'id' ];
$exists = false;将参数直接拼接入SQL执行
限制查询条数。
1
2
3// Check database
$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根据查询结果返回对应页面
与
Low
级别相同。
Impossible
源码分析
通过
token
验证身份1
2
3// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
$exists = false;从
request
中获取参数(GET)
与
Low
级别相同。以
PDO
方式预编译SQL参数查询1
2
3
4
5
6// 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();
$exists = $data->rowCount();根据查询结果返回对应页面
与
Low
级别相同。