标签:blog http os 使用 ar sp 数据 art 问题
PDO防注入的核心:查询语句模板和参数是分两次提交到mysql,另外参数转义由mysql自身完成。
PDO就是一个通用PHP数据库操作类,从php5开始提供,并从6开始成为默认的数据库操作接口;
由于PDO使用预编译的形式进行操作数据库,因此只要不是底层的漏洞(php 5.3.8之前的PDO存在漏洞),可以100%抵挡注入漏洞!
PDO默认并不是安全的,必须禁用pdo的prepared statements的仿真效果
$dbh = new PDO("mysql:host=localhost; dbname=demo", "user", "pass"); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);//禁止PHP本地转义而交由MySQL Server转义才是安全的,为什么呢?看下面代码
$dbh->exec("set names ‘utf8‘"); $sql="select * from test where name = ? and password = ?"; $stmt = $dbh->prepare($sql); $exeres = $stmt->execute(array($testname, $pass)); if ($exeres) { while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { print_r($row); } } $dbh = null;
关键在其机制:当调用 prepare() 时,查询语句已经发送给了数据库服务器,此时只有占位符 ? 发送过去,没有用户提交的数据;当调用到 execute()时,用户提交过来的值才会传送给数据库,他们是分开传送的,
两者独立的(由MySQL完成变量的转义处理),SQL攻击者没有一点机会。,但需要在DSN中指定charset属性,如:
$pdo = new PDO(‘mysql:host=localhost;dbname=test;charset=utf8‘, ‘root‘);
但是我们需要注意的是以下几种情况,PDO并不能帮助你防范SQL注入
1、你不能让占位符 ? 代替一组值,如:
SELECT * FROM blog WHERE userid IN ( ? );
2、你不能让占位符代替数据表名或列名,如:
SELECT * FROM blog ORDER BY ?;
3、你不能让占位符 ? 代替任何其他SQL语法,如:
SELECT EXTRACT( ? FROM datetime_column) AS variable_datetime_element FROM blog;
EXTRACT:用于抽取时间的单独部分如天,秒等
4.给mysql Server指定字符集,并将变量发送给MySQL Server完成根据字符转义才能防止注入,看下面例子就不能防止注入
$pdo->query(‘SET NAMES GBK‘);
$var = chr(0xbf) . chr(0x27) . " OR 1=1 /*";
$query = "SELECT * FROM info WHERE name = ?";
$stmt = $pdo->prepare($query);
$stmt->execute(array($var));
有个问题,如果在DSN中指定了charset, 是否还需要执行set names <charset>呢?
是的,不能省。set names <charset>其实有两个作用:
A. 告诉mysql server, 客户端(PHP程序)提交给它的编码是什么
B. 告诉mysql server, 客户端需要的结果的编码是什么
也就是说,如果数据表使用gbk字符集,而PHP程序使用UTF-8编码,我们在执行查询前运行set names utf8, 告诉mysql server正确编码即可,无须在程序中编码转换。这样我们以utf-8编码提交查询到mysql server, 得到的结果也会是utf-8编码。省却了程序中的转换编码问题,不要有疑问,这样做不会产生乱码。
标签:blog http os 使用 ar sp 数据 art 问题
原文地址:http://www.cnblogs.com/xjg6699/p/4029415.html