来源:自学PHP网 时间:2015-04-17 11:59 作者: 阅读:次
[导读] 首先查看以下代码$pdo-query(#39;SET NAMES GBK#39;);$var = chr(0xbf) . chr(0x27) . OR 1=1 /*;$query = SELECT * FROM test WHERE name = ? LIMIT 1;$stmt = $pdo-prepare(......
首先查看以下代码
$pdo->query('SET NAMES GBK');
$var = chr(0xbf) . chr(0x27) . " OR 1=1 /*";
$query = "SELECT * FROM test WHERE name = ? LIMIT 1";
$stmt = $pdo->prepare($query);
$stmt->execute(array($var));
1.设置字符集
SET names x等同于以下内容:
SET character_set_client = x
SET character_set_results = x
SET character_set_connection = x
2.设置payload www.2cto.com
3.深入分析
mysql的prepare其实是本地PHP客户端模拟的,并没有根据你mysql的设置做字符集的调整。应该交与mysql server端做prepare,同时得调用mysql_set_character_set去操作,server才会按照字符集去做转义。
php本地模拟的prepare底层就是mysql_real_escape_string,所以必须得用mysql_set_character_set去设置mysql->charset,否则就存在字符集问题。
也就是说在php本地调用pdo prepare中的mysql_real_escape_string来操作query,使用的是本地单字节字符集,即编码为\xbf\x5c\x27,并带入到mysql中查询,由于使用set names设置了连接字符集,mysql使用内部操作字符集gbk来进行操作,即执行
"SELECT * FROM test WHERE name = 'xxx' or 1=1 /* LIMIT 1";从而注入成功
解决方案:使用mysql_set_character_set函数来设置字符集。
|
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com