文章总结: 本文深入解析sqli-labs第32关,阐述了利用GBK等多字节字符集绕过PHPaddslashes()函数防御的原理。通过构造%df等高字节使反斜杠被MySQL解析为汉字的一部分,导致单引号转义失效,从而成功进行显错与联合查询注入。文章强调安全机制依赖环境上下文,开发需严格确保字符集配置一致以防此类漏洞。 综合评分: 94 文章分类: WEB安全,渗透测试,漏洞分析
当转义失效:从 sqli-labs 第 32 关看字符集如何击穿 addslashes
原创
武文学网安 武文学网安
武文学网安
2026年1月23日 01:05 中国香港
大家好,我是武文。
在进入第 32 关之前,先简单交代一下进度上的取舍。
在 第 29 关 中,我们已经系统学习了 HTTP 参数污染(HPP) 的注入思想; 第 30 / 31 关本质仍然是 HTTP 参数污染,只是闭合方式从单引号变为双引号,因此不再展开,直接进入一个全新的考点。
一、第 32 关整体说明
第 32 关的官方标题:GET – Error based – Bypassing addslashes()
这一关的关键词只有一个: addslashes()
| 项目 | 说明 | | — | — | | 请求方式 | GET | | 页面回显 | 有报错 | | 注入类型 | 显错注入 | | 核心考点 | PHP 转义函数绕过 | | 本质问题 | 字符集不一致导致转义失效 |
这一关第一次把重点从过滤规则转移到了 “防御函数本身是否可靠”。
二、原理:addslashes() 真的安全吗?
2.1 addslashes() 在做什么?
addslashes() 是 PHP 中一个非常常见的防御函数,用于给特殊字符加反斜杠:
' → \'" → \"\ → \\NULL → \0
设计初衷是: 防止单引号破坏 SQL 语句结构
很多初学者甚至会形成一种错觉:“只要用了 addslashes(),就不会有 SQL 注入了。”
第 32 关,就是专门用来打破这个错觉的。
2.2 问题的根源:字符集不一致
addslashes() 的工作方式有一个隐含前提:它假设:一个字符 = 一个字节
但在真实环境中,尤其是 MySQL 使用 GBK / BIG5 等多字节字符集时,这个前提并不成立。
在 GBK 编码中:
- 一个汉字 = 两个字节
- 某些字节组合 恰好包含 0x5c(\)
这就会导致一个致命问题:addslashes() 转义的 \,可能只是多字节字符的一部分
一旦 MySQL 在解析时:
- 把这两个字节当作一个合法字符
- 而不是「转义 + 引号」
👉 转义就失效了
三、第 32 关实战通关
3.1 注入点确认
基础测试:
?id=1 → 正常?id=1' → 正常?id=1" → 正常
在Hint中发现单双引号都被加了‘\’,也就是说被addslashes() 转义为 \'
3.2 构造绕过思路(核心)
这一关的目标其实非常明确:让 MySQL 在解析时,“忽略” addslashes() 加上的反斜杠。
在ASCII编码中,反斜杠是0x5C。
addslashes() 的防御逻辑正是围绕它展开的——只要在单引号前加上 0x5C,就认为 SQL 结构被安全地转义了。
问题在于: 👉 MySQL 并不是总按 ASCII 解析字符串。
① 利用点:GBK 多字节编码
在 GBK 编码 中,一个字符通常由 两个字节 组成:
[高字节] [低字节]
而在 GBK 的字符集中,存在一类高字节范围为 0x81–0xFE 的字符,它们的低字节可以恰好是 0x5C(反斜杠)。
这就产生了一个关键效果:0x5C 不再是“转义符”,而是“汉字的一部分”
② addslashes() 为什么会失效?
假设我们提交如下 payload(URL 编码):
%df%27
处理过程如下:
1️⃣ PHP 层(addslashes)看到的是:
0xDF 0x27 → 0xDF 0x5C 0x27
也就是
%df\'
2️⃣ MySQL 层(GBK 编码)看到的是:
0xDF 0x5C → 一个合法的 GBK 汉字0x27 → 单引号
此时:
\并没有作为转义符存在- 单引号重新获得 SQL 语义
③ 最终结果
addslashes() 以为自己完成了转义 MySQL 实际上把转义字符“吃掉”了
最终效果就是:
- 单引号成功闭合
- SQL 结构被重新打断
- 注入成立
👉 这正是第 32 关的核心突破点。
我在mysql中尝试用df来验证能否正常查询结果:
可以看到id=’1df\”仍然能够正常查询结果。
3.2.1 不止 %df:常见可用绕过字节总结
这里非常关键的一点是:并不是只有 %df能绕过 addslashes()
只要满足条件:
[GBK 高字节] + 0x5C
常见可用示例:
| | | | — | — | | 绕过字节 | URL编码形式 | | DF | %df%27 | | BF | %bf%27 | | A1 | %a1%27 | | A2 | %a2%27 | | A3 | %a3%27 |
这些字节的共同点是:
- 位于 GBK 高字节区间
- 与
0x5C组合后可构成合法多字节字符
⚠️ 注意: 是否成功还与 数据库字符集 / 连接字符集 有关,并非所有环境都通用。本质上并不是这些字节“特殊”,而是它们位于 GBK 高字节区间,在 addslashes 插入 0x5C 后,仍能被 MySQL 解释为一个完整字符。
3.2.2 为什么这个漏洞在真实环境中非常危险?
因为它揭示了一个根本性问题:addslashes() 只在“字符集假设成立”的前提下才安全
一旦出现:
- GBK / BIG5
- 历史项目
- 错误的字符集配置
那么:
- 防御代码“看起来很安全”
- 实际却是 完全失效
3.3 实际 payload(显错注入)
测试能否绕过反斜杠,构造payload:
?id=1%df' 报错?id=1%df" 正常?id=1%df' --+ 正常
加入%df后单引号会引发语法错误,加入注释符后正常。说明闭合方式为单引号。
3.4 测试XPATH显错注入:
?id=1%df' and updatexml(1,concat(0x7e,database(),0x7e),1)--+
能够成功利用显错获取数据。
3.5 UNION 注入验证
继续验证 UNION:
?id=-1%df' union select 1,2,3--+
依然能够成功注入。
至此:
- 显错注入 ✔
- UNION 注入 ✔
第 32 关正式通关。
四、第 32 关在整个 sqli-labs 中的意义
如果回头看前面的关卡,会发现一条非常清晰的设计路径:
| 阶段 | 关注点 | | — | — | | 1–20 | SQL 语法与注入基础 | | 21-24 | 请求体注入方式 | | 25–28 | 黑名单过滤的脆弱性 | | 29–31 | HTTP 参数解析问题 | | 32 | 防御函数自身的安全边界 |
第 32 关第一次明确告诉我们:安全函数不是银弹,安全必须建立在完整上下文之上
五、总结
第 32 关并没有引入新的 SQL 技巧,却第一次把视角从「怎么过滤」转向了「防御本身是否可靠」。
它揭示了一个经常被忽视的事实:安全不是函数本身的属性,而是上下文的结果。
addslashes() 在假设「单字节字符集」时看似安全,一旦进入 GBK 等多字节环境,转义逻辑就可能被字符解析过程吞噬。
这一关真正教会我们的不是某个 %df payload,而是一个更重要的安全认知:SQL 注入从来不只是 SQL 的问题,它同时属于字符编码、解析顺序与环境假设。
任何脱离上下文讨论的“安全防御”,本身就是不完整的。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:武文学网安 武文学网安 武文学网安《当转义失效:从 sqli-labs 第 32 关看字符集如何击穿 addslashes》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论