宽字节注入(GBK编码)


什么是宽字节

GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。宽字节带来的安全问题主要是吃ASCII字符(一字节)的现象。
我们以GBK编码为例进行讲解:
尽管现在呼吁所有的程序都使用unicode编码,所有的网站都使用utf-8编码,来一个统一的国际规范。但仍然有很多,包括国内及国外(特别是非英语国家)的一些cms,仍然使用着自己国家的一套编码,比如gbk,作为自己默认的编码类型。
GBK是一种多字符的编码。我们需要注意的是一个gbk编码汉字,占用2个字节。一个utf-8编码的汉字,占用3个字节。

addslashes()函数

addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。预定义字符包括:

单引号(')
双引号(")
反斜杠(\)
NULL

注入分析

我们以sqli-labs的Less-32来分析这种注入。 在题目,我们使用了一个addslashes函数,将$id的值转义。这是通常cms中对sql注入进行的操作,只要我们的输入参数在单引号中,就逃逸不出单引号的限制,无法注入。
当我们传入的参数为1'时,可以发现没有报错,从下面的hint可以发现我们的'已经被转义了。
?id=1'
那么怎么逃过addslashes的限制?众所周知addslashes函数产生的效果就是,让’变成',让引号变得不再是“单引号”,只是一撇而已。一般绕过方式就是,想办法处理'前面的:

1.想办法给\前面再加一个\(或单数个即可),变成\\',这样\被转义了,'逃出了限制。
2.想办法把\弄没有。

我们这里的宽字节注入是利用mysql的一个特性,mysql在使用GBK编码的时候,会认为两个字符是一个汉字(前一个ascii码要大于128,才到汉字的范围)。如果我们输入%df’看会怎样:
?id=1%df'
可以看到,这样已经报错了。也就说明我们的语句被插入到了sql语句中并被执行了。
为什么从刚才到现在,只是在’也就是%27前面加了一个%df就报错了?而且从图中可以看到,报错的原因就是多了一个单引号,而单引号前面的反斜杠不见了。 这就是mysql的特性,因为gbk是多字节编码,他认为两个字节代表一个汉字,所以%df和后面的也就是%5c变成了一个汉字“運”,而’逃逸了出来。
那么mysql怎么判断一个字符是不是汉字,根据gbk编码,第一个字节ascii码大于128,基本上就可以了。比如我们不用%df,用%a1也可以。

payload

payload

总结

如果数据库编码为 GB2312 的话是没有办法进行宽字节注入的。
这归结于gb2312编码的取值范围。它的高位范围是0xA1~0xF7,低位范围是0xA1~0xFE,而是0x5c,是不在低位范围中的。所以,0x5c根本不是gb2312中的编码,所以自然也是不会被吃掉的。

所以,把这个思路扩展到世界上所有多字节编码,我们可以这样认为:只要低位的范围中含有0x5c的编码,就可以进行宽字符注入。

最后修改:2021 年 08 月 08 日 09 : 54 AM
如果觉得我的文章对你有用,请随意赞赏