0x00概述
宽字节注入主要源于程序员设置数据库编码与php编码设置为不同的两种编码,那么就可能产生宽字节注入
例如:PHP编码为UTF-8而Mysql的编码设置为set names 'gbk'或是set character_set_client=gbk,这样配置会引发编码转换从而导致的注入漏洞(一个gbk编码汉字,占用2个字节,一个utf-8编码的汉字,占用3个字节)
注意:set name 'x'与以下三个语句等价:
mysql->set charater_set_client=x;
mysql->set charater_set_results=x;
mysql->set charater_set_connection=x;
也就是说当你设置了set names 'x'时就同时执行了上面3条语句
宽字节注入就是PHP发送请求到Mysql时使用了语句set names 'gbk'或是set character_set_client=gbk进行了一次编码,但是又由于一些不经意的字符集转换导致了宽字节注入
0x01宽字节注入原理
1、在我们正常使用addslashes函数或是开启PHP的GPC(如果magic_quotes_gpc=on,php解析器就会自动为post、get、cookie过来的数据增加转义字符"\",以确保这些数据不会引起程序,特别时数据库语句因为特殊字符(认为是PHP的字符)引起的污染,插入后在数据库里显示的是转义前的原始数据,所以取出来不用转义)时过滤get、post、cookie、requst提交的参数时,我们使用的预定义字符会被转义成添加反斜杠的字符串
0x02实例
在php中使用$pdo->query('set names gbk');指定三个字符集(客户端、连接层、结果集)都是gbk编码。而php的编码为utf-8编码时造成宽字节注入
加了单引号没有报错,可以看出我们输入的 ' 已经给addslashes函数过滤掉了
那么如何逃过addslashes的限制呢?
addslashes函数产生的效果就是,让(')变成(\'),让单双引号变得不再是“单双引号”,只是一撇而已。一般的绕过方法是,想办法处理掉(\')前面的(\):
1、给(\)前面再加上一个(\),变成(\\'),这样(\)被转义了,(’)逃出了限制
2、想办法把(\)去掉
eg.mysal在使用gbk编码的时候,会认为两个字符是一个汉字(前一个ASCII码要大于128,才到汉字的范围),所以%df和后面的\也就是变成了一个汉字,'就逃逸了出来。
sql语句出错,说明可以注入。
不会报错,因为%df%df是一个汉字,%5c%27不是汉字,仍是\'
然后我们就可以构造一个exp获得管理员账号密码
http://localhost/index.php?id=-1%df%27union%20select%201,2,concat(name,0x23,pass)%20from%20admin%23