Files
Sec-Interview/_book/Chapter4/4-20.md
T
2025-11-08 21:00:06 +08:00

84 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
### 单引号被过滤怎么绕过
**1. 使用双引号**
如果后端代码在 SQL 查询中使用了双引号 `"` 来包裹字符串,那么你可以尝试用双引号进行注入
**原始查询:** `SELECT * FROM users WHERE username = "$username"`
**注入尝试:** `username=" or 1=1 -- "`
**最终执行的 SQL** `SELECT * FROM users WHERE username = "" or 1=1 -- "`
这种情况并不常见,因为多数开发者会优先使用单引号。但它是一个很好的起点,值得尝试
**2. 使用十六进制编码**
有些数据库(如 MySQL)允许使用十六进制编码来表示字符串。你可以将单引号 `'` 或整个字符串(如 `or 1=1`)进行十六进制编码,然后通过 `0x` 前缀传入
**原始查询:** `SELECT * FROM users WHERE id = '...注入点...'`
**注入尝试:** 假设你要注入 `or 1=1`,单引号 `'` 的十六进制是 `0x27``' or 1=1 -- ` 的十六进制是 `0x27206f7220313d31202d2d20`
**完整 URL 注入:** `id=0x27206f7220313d31202d2d20`
**最终执行的 SQL** `SELECT * FROM users WHERE id = 'or 1=1 -- '`
虽然这看起来很直接,但实际应用中,你需要将整个注入语句进行十六进制编码,因为后端可能不仅过滤单引号,还可能过滤其他关键字
**3. 使用宽字节注入**
宽字节注入是一种专门针对 PHP 的 `addslashes()` 函数和 `magic_quotes_gpc` 配置的绕过技术。在某些字符集(如 GBK)中,一个汉字占用两个字节
当服务器使用 `addslashes()` 函数时,它会将单引号 `'` 转义为 `\'`。在 ASCII 编码下,`\` 的十六进制是 `0x5c``'``0x27`,所以 `\'` 就是 `0x5c27`
但如果后端数据库使用了 GBK 编码,且它将 `0x5c` 和它前面的一个字节组合成一个汉字时,那么 `\'` 中的 `\` 就会被“吃掉”,从而使得后面的单引号 `'` 重新生效
**攻击步骤:**
1. 找到一个 GBK 编码的网站
2. 在 URL 中注入一个宽字节,例如 `%df`
3. 然后注入单引号
**注入尝试:** `id=1%df%27`
**服务器端处理:**
1. PHP 的 `addslashes()` 函数收到 `%df'`
2. 它在 `'` 前面加上 `\`,变成 `%df\'`
3. URL 编码后,`%df\'` 变为 `%df%5c%27`
4. 当这个字符串传到数据库时,GBK 编码会把 `%df%5c` 当作一个汉字,`%27` 就会单独留下,恢复成单引号 `'`
**最终执行的 SQL** `SELECT * FROM users WHERE id = '1運''...` (`'運'` 是一个汉字) 后面的 `'` 就成为我们控制的单引号,可以用来闭合语句
**4. 使用反斜线 `\` 绕过 `addslashes`**
在某些情况下,如果后端代码没有过滤反斜线,你可以通过注入一个反斜线来“吃掉” `addslashes` 自动添加的反斜线
**原始查询:** `SELECT * FROM users WHERE id = '...注入点...'`
**注入尝试:** `id=1\'`
**服务器端处理:**
1. PHP 的 `addslashes()` 函数收到 `1'`
2. 它在 `'` 前面加上 `\`,变成 `1\'`
3. 如果前端的输入是 `1\'` `addslashes` 会将 `\'` 变为 `\\'`
这个方法需要深入理解后端如何处理输入。如果后端代码只对单引号进行了转义,而没有对反斜线进行处理,你就可以用一个反斜线来闭合它
**5. `char()` 函数绕过**
`char()` 函数可以将数字转换为字符。你可以利用这个函数来构造单引号
**注入尝试:** `id=1 and 1=1 and (select char(39))` `id=1 union select 1,2,3 from users where username=char(39)adminchar(39)`
这种方法通常用于绕过对特定字符串(如 `'`)的过滤,但不能绕过对整个注入语句的过滤
**6. 使用 `like` 语句绕过**
在某些盲注场景下,如果无法使用单引号,可以尝试使用 `like` 语句来代替 `union``and`
**注入尝试:** `id=1 and 1 like 1 and 1=1 --` `id=1 and 1 like database()`
这种方法适用于特定的 SQL 语句结构,但并非万能