宽字节注入漏洞原理

我们通过一个经典的例子来解释这个漏洞

假设一个 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 编码进行解析。它会发现 %df0xdf)是一个宽字节的开头,并且紧接着的 \0x5c)恰好在GBK编码的合法范围内,可以和 0xdf 组成一个合法的汉字

    • %df%5c (0xdf0x5c) 在GBK编码中是一个合法的汉字,例如“運”
    • 结果: 1%df\' 在数据库看来就变成了 1 + 一个汉字 + '
  • 最终的 SQL 查询: SELECT * FROM users WHERE id = '1運''

    此时,被转义的单引号 ' 重新获得了生命,因为它不再被认为是转义符的一部分。攻击者就可以继续使用后面的单引号进行SQL注入

Copyright © 版权信息 all right reserved,powered by Gitbook该文件修订时间: 2025-09-25 03:13:16

results matching ""

    No results matching ""