原理
宽窄字节
字符大小为一个字节(英文默认一个字节)称为窄字节,为两个字节(汉字默认两个字节)的称为宽字节,比如:GB2312、GBK、GB18030、BIG5、Shift_JIS 等。
宽字节注入
直接举例:我们在注入时如果后台做了防御,输入的符号被转义,比如:?id=1' union select 1,2,3 --+,『1'』 被转义成『1\'』,这时这条语句是无法进行注入的,整条语句被看做了是字符串,这时候我们就要想办法把『 \ 』干掉,删肯定是删不掉的,但是可以把它变成不是『 \ 』,它就失去了转义的作用,这条注入也可以正常执行。
如何变成不是『 \ 』,就是今天要说的宽字节,『 \ 』的编码是:%5c,而当 MySQL 使用 GBK 编码时,会把两个字符认作一个汉字,编码:%df%5c,就是一个汉字『運』,所以我们可以把注入语句弄成:?id=運' union,就消灭掉了『 \ 』。
也就是说 GBK 编码处理编码的过程中存在问题,可以通过在注入点加上『%df』构造数据绕过转义防御,然后按照正常注入流程开始即可。
练习
sqli-labs 的 less-32
判断列数:
?id=1%df' order by 3 --+,改成 4 报错,可见正确注入了,且得到列数为 3,剩下的语句就不多说了,和之前的注入都一样,只是多个 『%df』
宽字节注入如何发现
如果是黑盒测试,那就只能在注入点输入『%df』进行测试了。
如果是白盒测试:
- 查看 MySQL 编码是否为 GBK
- 是否使用了 preg_replace 把单引号替换成了 『\'』
- 是否使用了 addslashes 进行转义
- 是否使用了 mysql_real_escape_string 进行转义
防御
知道如何发现,防御就很简单了
- 使用 utf-8
- 使用 mysql_real_escape_string 时,需要配合 mysql_set_charset('gbk', $conn)
- 设置参数:character_set_client = binary,使用二进制进行数据库的连接
网友评论