【问题标题】:PDO parameters not working at allPDO 参数根本不起作用
【发布时间】:2011-04-21 00:23:19
【问题描述】:

我正在浏览一些代码并将其中的数据库部分更改为使用 PDO。到目前为止一切正常,除了我准备好的语句中的参数。出于某种原因,下面的代码根本不起作用。这两个 $_GET 变量基本上用于在特定页面上进行排序。查询本身可以在不使用参数的情况下正常工作,如果我在最后手动输入“ORDER BY id DESC”,那也可以正常工作。我似乎无法让它与可变参数一起工作。代码如下:

$sort = $_GET['sort'];
$order = $_GET['order'];
$statement = $db->prepare('SELECT uid, id, fname, lname, ext, uname
  , email, access, created, modified, last_login, enabled 
  FROM users 
  ORDER BY :col :or');
$statement->bindParam(':col', $sort);
$statement->bindParam(':or', $order);
$statement->execute();
$num = $statement->rowCount();

有什么建议吗?

谢谢

【问题讨论】:

标签: php mysql sql pdo


【解决方案1】:

当将参数作为参数传递给ORDER BY 子句时,它们被视为文字表达式。如果要按列或别名排序,则需要传递标识符。在 MySQL 中,这些由不带引号的字符串表示,或者最好是用反引号引用的字符串表示,例如

ORDER BY `fname`

同样,方向常数,当存在时必须使用ASCDESC 这两个关键字中的任何一个。我不确定如果您尝试使用参数(将被评估为表达式)会发生什么。


这是我过去使用允许的可排序列的映射的方法...

$orderCols = array(
    'firstName' => 'fname',
    'lastName'  => 'lname'
);
$sort = isset($_GET['sort'], $orderCols[$_GET['sort']])
    ? $orderCols[$_GET['sort']
    : 'uid'; // some sane default

$order = isset($_GET['order']) && $_GET['order'] == 'DESC'
    ? 'DESC' : 'ASC';

$query = sprintf('SELECT uid, id, fname, lname, ext, uname, email, access, created, modified, last_login, enabled FROM users ORDER BY `%s` %s',
    $sort, $order);
$statement = $db->prepare($query);

【讨论】:

  • 使用参数作为伪关键字根本行不通!这是(部分)使用参数可以防止 SQL 注入攻击的原因。
  • 你是说我的语句中没有正确使用参数? PHP 的文档在 WHERE 子句中使用它们,所以我认为我的应该可以正常工作(但事实并非如此):php.net/manual/en/pdostatement.bindparam.php
  • +1 正是我想说的 :) 顺便说一句,我认为您可以省略方向关键字,它将假定为 ASC
  • 感谢您对此进行详细说明。我看到你使用 sprintf() 做了什么,明天在工作中试试这样的东西。
【解决方案2】:

使用参数作为伪关键字根本行不通!
这是(部分)使用参数可以防止 SQL 注入攻击的原因。

当然,既然您可以操作字符串,您只需在其中插入“DESC”/“ASC”,重新打开整个 SQL 注入孔。

因此 :col 将被接受为字段。至于 $order 我会推荐类似的代码

伪代码(不是真正的php)

if uppercase($order) <> 'DESC' then $order = 'ASC';
$query = 'select ... '+ $order;

显式测试将任何注入代码转换回“ASC”,这样可以安全地破解它。

当然,对于字段,您也可以对所有可能的字段名称进行显式测试。只要您确保可能的结果只能是有效字段名称,您就很好,但它是如履薄冰。

警告
现在您(可能)重新开始操作查询字符串,您也重新回到 SQL 注入领域,所以要非常小心您所做的事情。

【讨论】:

  • 我认为单独使用带有 PDO 的准备好的语句可以解决大多数 SQL 注入问题。我错了吗?我还需要清理我的参数吗?
  • 否,但您只能参数化值,因此,如果您想通过粘贴字段名或订单方向 (ASC/DESC) 来操作查询,您将回到黑客 SQL 查询字符串,从而回到SQL注入土地。
  • 忘了感谢您的帮助和澄清我现在面临的 SQL 注入威胁。我希望我现在可以在明天早上解决这个问题:)
  • @Aaron,不客气。祝你好运,继续努力。
猜你喜欢
  • 2012-03-23
  • 2011-12-01
  • 1970-01-01
  • 2012-09-17
  • 1970-01-01
  • 1970-01-01
  • 2012-08-17
  • 1970-01-01
  • 2016-03-17
相关资源
最近更新 更多