为什么PDO手册说PDO仍然可以进行SQL注入?

时间:2012-05-17 12:16:14

标签: php mysql

http://php.net/manual/en/pdo.prepared-statements.php

  

如果应用程序专门使用预准备语句,开发人员可以确保不会发生SQL注入(但是,如果使用非转义输入构建查询的其他部分,仍然可以进行SQL注入)。

某些输入未转义的可能情况是什么?如果所有其他输入都使用PDO进入数据库,那么这是否可能?

我正在考虑使用mysql_ *函数处理其他输入而不使用mysql_real_escape_string进行转义的情况。还有什么可能是威胁吗?

非常感谢。此致

3 个答案:

答案 0 :(得分:8)

这意味着您无法直接使用不受信任的值,例如作为列名或表名 - 或作为LIMIT参数。

例如,这是安全的:

$query = "SELECT * FROM tbl WHERE col = ?";

虽然不是:

$query = 'SELECT * FROM tbl WHERE col = ? LIMIT ' . $_GET['limit'];
$query = 'SELECT * FROM tbl WHERE ' . $_GET['field'] . ' = ?';
$query = "SELECT * FROM tbl WHERE col = ? AND othercol = '" . $_GET['other'] . "'";
$query = 'SELECT * FROM ' . $_GET['table'] . ' WHERE col = ?';

基本上,预备语句的占位符用于您在经典查询中使用单引号内的转义值的地方。

如果您想知道为什么数据库通常不支持表名等内容的占位符:除了动态表/列名称不常见之外,数据库引擎通常会在准备好时自动优化准备好的语句。但是,如果不确切知道访问哪些表/列,则无法正确完成。

答案 1 :(得分:2)

考虑一下:

$sql = "SELECT * FROM ".$_GET['tablename']." WHERE somecol = ?";

因为我使用未转义的用户输入填充了表名,所以可以传入例如public_table p LEFT JOIN hidden_table h ON h.id = p.id并获得您不希望我的结果,即使您已将传递给的值转义为somecol比较。

关键是,虽然预处理语句安全地转义了您传递给查询中?的任何用户输入,但在将它传递给prepare()之前,它们无法转义已存在于字符串中的数据

答案 2 :(得分:0)

这意味着不要被引诱认为PDO是神奇药丸......如果你使用准备好的陈述,你仍然会很脆弱。