0

我对使用 PDO 还是很陌生,所以我不确定我是否正确地将其关闭,但是通过以下测试,我可以进行一些我想绕过的注入。

在我的模型类中,我有一些快捷方法。其中之一称为 return_all($table,$order,$direction) ,它只返回表中的所有行:

 public function return_all($table,$order = false, $direction = false) {
    try {
        if($order == false) {
            $order = "create_date";
        }
        if($direction != false && !in_array($direction,array("ASC","DESC"))) {
            $direction = "DESC";
        }
        $sql = "SELECT * FROM ".mysql_real_escape_string($table)." ORDER BY :order ".$direction;
        $query = $this->pdo->prepare($sql);
        $query->execute(array("order" => $order));
        $query->setFetchMode(PDO::FETCH_ASSOC);
        $results = $query->fetchAll();
    } catch (PDOException $e) {
        set_debug($e->getMessage(), true);
        return false;
    }
    return $results;
}

这很好用,除非我将以下内容作为 $table 传递给方法:

 $table = "table_name; INSERT INTO `users` (`id`,`username`) VALUES (UUID(),'asd');";

现在不太可能有人能够更改 $table 值,因为它被硬编码到我的控制器函数中,但是,我有点担心即使我使用 PDO 仍然能够进行一些注入。更令人惊讶的是 mysql_real_escape_string() 完全没有做任何事情,SQL 仍然运行并在 users 数组中创建了一个新用户。

我还尝试将表名设置为绑定参数,但由于在表名周围添加了 ``PDO,我假设出现 sql 错误。

有没有更好的方法来完成下面的代码?

4

1 回答 1

-1

你已经解决了你的方向问题。

if($direction != false && !in_array($direction,array("ASC","DESC"))) {
        $direction = "DESC";
    }

对表名使用相同的技术

$allowed_tables = array('table1', 'table2');//Array of allowed tables to sanatise query
if (in_array($table, $allowed_tables)) {
    $sql = "SELECT * FROM ".$table." ORDER BY :order ".$direction;
}
于 2013-03-21T17:31:28.017 回答