注入姿势-宽字符绕过

最小的字符集是ascii字符集,只有128个有效字符,用十六进制表示只是0x00-0x7F.随后由于网络发展,为了跨国家统一使用增大可以表示的字符就用两个字节表示一个字符,有了gb2312范围在[0xA1-0xF7][0xA1-0xFE](中间很多没有填满),它保证所有字节在A0以上,也就在7F以上了。

而另一种编码GBK编码则是完全兼容gb2312(就是说在gb2312字符集中每个字符位置,与gbk字符集里面位置完全一致,而且包含gb2312),但是,它有2万多个字符。从上面看,只能选择往下排序了。 就是从A1A0往下排了,我们发现它编码实际范围是:[0x81-0xFE]([0x40-0x7E|0x80-0xFE] ) (GBK编码),我们发现由2个字节组成,首字节范围在7F之上,而第2个字节,有一部分在0x40-0x7E了。这就是导致bug原因。

而宽字节绕过的前提条件是程序员设置MySQL连接时的错误配置,如下:set character_set_client=gbk,配置会引发编码转换从而导致绕过某些防护实现注入漏洞。具体分析一下原理:

  1. 正常情况下GPC开启或者使用addslashes函数过滤GET或POST提交的参数时,我们测试输入的',就会被转义为\';

  2. 若存在宽字节注入,输入%df%27时,经过单引号的转义变成了%df%5c%27,之后再数据库查询语句进行GBK多字节编码,即一个中文占用两个字节,一个英文同样占用两个字节且在汉字编码范围内两个编码为一个汉字。然后MySQL服务器会对查询语句进行GBK编码即%df%5c转换成汉字"運",单引号逃逸出来,从而绕过转义造成注入漏洞。

现在基本都会将mysql的连接配置设置为:[set character_set_client=binary]

SQL语句是SELECT * FROM news WHERE tid='{id}',根据文章的id把文章从news表中提取出来,根据文章的id把文章从news表中提取出来,在sql之前,我们只用了限制函数addslashes函数,对$id进行转义,只要我们输入参数在单引号中,就逃逸不出单引号的限制,从而无法注入。

我们这里利用的是mysql的一个特性,mysql在使用GBK编码的时候,会认为两个字节是一个汉字(前一个ascii码要大于128,才到汉字范围),我们测试输入%df'

已经报错,看到报错,说明sql语句出错,看到出错说明可以注入。报错的原因就是多了一个单引号,而单引号前面的反斜杠不见啦。这就是mysql的特性,因为gbk是多字节编码,它认为两个字节代表一个字符,所以%df和后面的%5c变成了汉字“運”,而’逃逸了出来。

因为是两个字节代表一个汉字,我们尝试%df%df%27

不报错了,因为%df%df组成了汉字"哌",%5c%27不是汉字,仍然是\'

mysql如何判断一个字符是不是一个汉字,根据gbk编码,第一个字节的ascii码大于128,基本上就行,若不用%df而用%a1也可以

%a1%5c虽然不是一个汉字,但一定会被mysql认为是一个宽字符,所以就能让后面的%27逃逸出来,构造一个exp,查询管理人员的账号密码。

GB12和GBK的区别

gb2312和gbk都是宽字节家族医院,但是当把数据库编码设置为关闭gb2312时,结果就不能注入

这主要是gb2312编码取值范围的事情,它高位范围0xA1~0xF7,低位范围是0xA1~0xFE,\是%5c,是不在低范围中的,即其根本不是gb2312遍吗,故其不会被吃掉。故只要低位的范围中含有0x5c的编码,就可以进行宽字节的注入

参考:https://www.cnblogs.com/bmjoker/p/9134830.html

猜你喜欢

转载自www.cnblogs.com/weak-chicken/p/12291441.html