4-5
约 480 字大约 2 分钟
2025-11-02
宽字节注入漏洞原理
我们通过一个经典的例子来解释这个漏洞
假设一个 PHP 应用在接收用户输入后,使用了 addslashes() 或 mysql_real_escape_string() 等函数来对单引号进行转义
正常情况下的过滤:
当用户输入 '(单引号)时,后端会被转义成 \'
- 输入:
id=1' - 转义后:
id=1\' - SQL 查询:
SELECT * FROM users WHERE id = '1\''
这句 SQL 语句是合法的,因为 \' 被视为一个转义后的单引号,从而导致查询失败,注入被阻止
宽字节注入的绕过:
当后端数据库使用 GBK 编码时,我们可以利用一个特殊字符来“吃掉”转义符 \
输入: 我们在单引号前加一个十六进制的宽字节,例如
%df完整的输入:
id=1%df'URL解码后:
id=1'(这里是0xdf的GBK编码,具体字符取决于浏览器)addslashes()处理后:addslashes()只会将单引号'转义成\'。 此时,字符串变为1%df\'- 在内存中,它的十六进制表示是:
31 25 64 66 5c 27 - 但在GBK编码环境下,数据库会重新解释这个字符串
MySQL 在接收到这个字符串时,会把它当作 GBK 编码进行解析。它会发现
%df(0xdf)是一个宽字节的开头,并且紧接着的\(0x5c)恰好在GBK编码的合法范围内,可以和0xdf组成一个合法的汉字%df%5c(0xdf和0x5c) 在GBK编码中是一个合法的汉字,例如“運”- 结果:
1%df\'在数据库看来就变成了1+ 一个汉字 +'
- 在内存中,它的十六进制表示是:
最终的 SQL 查询:
SELECT * FROM users WHERE id = '1運''此时,被转义的单引号
'重新获得了生命,因为它不再被认为是转义符的一部分。攻击者就可以继续使用后面的单引号进行SQL注入