简介
宽字节注入是一种在SQL注入绕waf的手法 在有的时候我们会遇见对于单引号双引号这类闭合符进行事先转义的情况 就比如一些常见的:
addslashes、mysql_real_escape_string、mysql_escape_string、php.ini中magic_quote_gpc的配置
这些都会在你的单引号或者双引号之前加上一个反斜杠进行转义 那么此时单双引号就失去了它的闭合作用 这种时候如果数据库使用了宽字节字符集的情况下 那么我们就可以尝试宽字节注入的方法了
原理
首先来了解宽字节编码 这是一种比较特殊的编码形式 这里就拿最常见的gbk编码来举例 数据库只要遇到一个处于高字节范围(大于 127,即十六进制大于 0x7F)的字符,它就会自动把它和紧跟在后面的一个字节组合起来,试图解析成一个汉字。
上面我们也说到了 有时候会在单引号前面自动加上反斜杠 那我们这里就简单了 输入一个大于127的字符 也就是高字节的字符 让数据库尝试将其转换成汉字 此时就会在高字节后面再找一个字符从而组合成汉字
payload:
1 | id=1%df' |
攻击者构造的经典 Payload:?id=1%df%27
执行流程拆解:
- 攻击者输入:
%df%27(%df是一个大于0x7F的随机高字节字符,%27是单引号)。 - PHP 防御层:
addslashes()发现有单引号,在其前面加上反斜杠\(%5c)。此时,字符串变成了:%df%5c%27。 - 数据库解析层:MySQL 接收到
%df%5c%27,按照 GBK 字符集进行解析。- 它首先读取到
%df,发现符合 GBK 高字节要求。 - 接着它会抓取紧跟其后的
%5c,将%df%5c组合在一起进行解码。巧合的是,%df%5c对应的正好是繁体汉字“運”。 - 于是,原本起转义作用的反斜杠
%5c被“吃掉”了,变成了汉字的一部分。
- 它首先读取到
- 最终结果:进入数据库的实际 SQL 语句变成了
... id='1運' ...。 此时,最后的那个单引号%27完美逃逸,成功闭合了前面的 SQL 语句,后续就可以顺理成章地拼接UNION SELECT等恶意代码了。
除了 %df,只要高字节 ASCII 码大于 127 且能和 %5c 组合成合法字符的十六进制都可以利用(如 %aa、%e5 等)。 另外,如果是在 HTTP Header 或 POST 表单中测试,通常需要配合抓包工具(如 Burp Suite)将对应的字符直接修改为 Hex 格式发送,或者直接使用 URL 编码发送,取决于 Web 容器的解析方式。