宽字节注入是利用多字节字符编码(如gbk)中高位字节的特性,通过构造特定输入使过滤函数误判字符边界,从而绕过转义防护的sql注入技术。其核心在于利用php早期版本中`magic_quotes_gpc`开启时使用的`addslashes()`函数与gbk编码的冲突:`addslashes()`仅对单字节进行转义,而gbk是双字节编码,当转义符(反斜杠\)被插入后,若紧随其后的是gbk的高位字节,两者结合会形成一个新的合法gbk汉字,导致原意中的引号逃逸出来。

GBK编码如何导致转义失效?
在GBK编码下,一个汉字由两个字节组成,且高位字节的ASCII码通常大于128(即0x80-0xFF)。当`addslashes()`处理输入时,它会将单引号'转换为\'。如果攻击者提交的输入包含%DF(GBK汉字“运”的高位字节)和',`addslashes()`会将'变为\'。此时,%DF与\结合变成了一个新汉字“连”,而剩下的'则脱离了转义状态,成功闭合了SQL语句中的字符串。

%df%27-- -
上述代码展示了具体的Payload。%df是GBK编码中的一个高位字节,%27是URL编码后的单引号。经过`addslashes()`处理后,%df和\(即%5c)组合成一个GBK汉字,剩下的%27(单引号)成为未转义的字符,从而实现了注入。
为什么现代环境不再受此影响?
随着PHP版本的更新,`magic_quotes_gpc`功能已被废弃并移除,同时PDO等预处理机制成为主流,宽字节注入的攻击面已大幅缩小。然而,理解这一原理对于排查遗留系统或分析历史漏洞仍具有重要意义。在现代开发中,应始终使用参数化查询来防止SQL注入,而不是依赖简单的字符串过滤。

$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$_GET['id']]);
以上代码展示了使用PDO预处理语句的正确做法。通过将用户输入作为参数传递,数据库驱动会自动处理转义和类型检查,从根本上杜绝了SQL注入的可能性。这种方法是当前Web应用安全开发的标配。
基于程序中某个输入、条件或结果的具体问题
在实际测试中,如果尝试使用%df%27作为输入,但发现注入失败,可能是因为服务器端使用了UTF-8编码而非GBK。在UTF-8编码中,三个字节才构成一个汉字,因此%df%5c无法组合成有效字符,单引号依然会被正确转义。此外,如果使用了`mysql_set_charset('gbk')`显式设置连接字符集,也可能影响注入效果,需根据具体环境调整Payload。











