### 宽字节注入漏洞原理

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

假设一个 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注入