8

可能重复:
准备好的语句如何防止 SQL 注入攻击?

对于我们这些刚接触 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_*use mysql_real_escape_stringwhich 只是把文字\. PDO 是否使用相同的系统?如果没有,就卫生而言,我们依靠什么?

4

2 回答 2

4

虽然您的查询中似乎没有任何内容可以作为输入进行清理。此外,如果您只是输入查询,它不会对它做任何事情。

但它确实具有称为prepared statements的魔力,它确实对您有所帮助。您可以查看@yourcommonsense 的链接以获取更多信息:

准备好的语句如何防止 SQL 注入攻击?

于 2013-01-29T15:25:24.700 回答
-1

PDO 具有PDO::Quote()mysql_real_escape_string(). 这提供了基本相同的功能和 sme 级别的安全性。

更好的选择是“Prepared Statements”功能,您可以在其中将标记而不是变量放入查询中PDO::prepare(),然后使用PDO::execute()将变量传递给查询。

这更安全,因为它使用数据库引擎的内部机制将变量推送到查询中。通过准备好的语句进行 SQL 注入攻击的可能性为零(除非数据库引擎本身存在错误,但通过保持 MySQL 版本更新可以缓解这种情况;与您自己的代码无关)。

准备好的语句还有一个好处是它们可以被数据库引擎缓存。这意味着,如果您使用相同的查询但使用不同的变量值进行多次调用,那么与使用旧的基于字符串的机制进行相同的查询相比,您将获得性能提升。

注意:有些 DB 本身可能不支持预处理语句,在这种情况下 PHP 会模拟它们。在这种情况下,它与 using 基本相同PDO::Quote,并且您不会获得上面列出的好处。大多数数据库确实支持它们,但即使那样它也有可能被禁用,所以请确保你关闭ATTR_EMULATE_PREPARES

最后,使用 PDO 更安全,因为旧的 mysql 扩展在其核心存在一些基本的安全问题。例如,旧 API 不加密 PHP 和 MySQL 数据库之间的通信。这意味着理论上存在窃听者攻击的风险,尤其是当数据库与 PHP 不在同一台服务器上时。PDO 使用更新版本的 MySQL 通信协议,因此能够加密此流量,因此更安全(这也是 PDO 不支持真正古老版本的 MySQL 的原因)。旧 API 还存在一些其他类似的隐藏风险,这些风险在代码中根深蒂固,无法消除。这就是为什么mysqli扩展被编写为直接替代它的原因。

于 2013-01-29T16:13:24.820 回答