可能重复:
How prepared statements can protect from SQL injection attacks?
对于我们这些刚接触PDO的人来说,我们认为它更安全,使用起来更好,但我无法理解的是,这是如何安全的?
<?php
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8', 'username', 'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
try {
//connect as appropriate as above
$db->query('hi'); //invalid query!
} catch(PDOException $ex) {
echo "An Error occured!"; //user friendly message
some_logging_function($ex->getMessage());
}
foreach($db->query('SELECT * FROM table') as $row) {
echo $row['field1'].' '.$row['field2']; //etc...
}
?>
请注意,我确实理解它的作用,但它对消毒输入的确切作用是什么?我知道mysql_*
使用mysql_real_escape_string
只是放置文字\
。 PDO是否使用同一系统?如果没有,我们在卫生方面依赖什么?
答案 0 :(得分:4)
虽然在您的查询中似乎没有任何可以清理的输入。此外,如果你只是提出你的查询,它将不会做任何事情。
但它确实有一种名为prepared statements的魔法,会帮助你。您可以查看@yourcommonsense的链接以获取更多相关信息:
How can prepared statements protect from SQL injection attacks?
答案 1 :(得分:-1)
PDO使用PDO::Quote()
方法执行与mysql_real_escape_string()
相同的工作。这提供了基本相同的功能和安全级别。
更好的选择是“准备语句”功能,您可以使用PDO::prepare()
将标记放入查询而不是变量,然后使用PDO::execute()
将变量传递给查询。
这更安全,因为它使用数据库引擎的内部机制将变量推送到查询中。通过准备好的语句没有发生SQL注入攻击的可能性(除非数据库引擎本身有错误,但是你可以通过保持MySQL版本的最新修补来缓解这种情况;与你自己的代码无关)。 p>
准备好的语句还有奖励,它们可以由数据库引擎缓存。这意味着如果您使用相同的查询进行多次调用但具有不同的变量值,那么与使用旧的基于字符串的机制进行相同的查询相比,您将获得性能提升。
注意:某些DB本身可能不支持预处理语句,在这种情况下,PHP将模拟它们。在这种情况下,它与使用PDO::Quote
基本相同,并且您没有获得上面列出的好处。大多数数据库确实支持它们,但即便如此,它也可能被禁用,因此请确保关闭ATTR_EMULATE_PREPARES
。
最后,使用PDO更安全,因为旧的mysql扩展在其核心有一些基本的安全问题。例如,旧的API不会加密PHP和MySQL数据库之间的通信。这意味着存在窃听者攻击的理论风险,特别是如果DB与PHP不在同一服务器上。 PDO使用更新版本的MySQL通信协议,因此能够加密此流量,因此更安全(以及PDO不支持真正古老版本的MySQL的原因)。旧的API还有一些其他类似的隐藏风险,这些风险在代码中根深蒂固,无法删除。这就是mysqli
扩展名被编写为直接替代它的原因。