【问题标题】:PDO SQL injection test on search query搜索查询的 PDO SQL 注入测试
【发布时间】:2013-03-21 16:12:43
【问题描述】:

我对使用 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 错误。

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

【问题讨论】:

  • @summea,我尝试将 :table 设置为绑定参数,但 sql 抱怨 SQL 错误。我认为这是由于 PDO 放在表名周围的``
  • 如果您不使用保留字作为表名,则不需要在表名周围加上 `` 引号。此外,据我所知,我认为您不需要 mysql_real_escape_string(),因为 PDO 会在内部自动为您执行此操作 xd
  • @aleation:我可以肯定地确认执行“SELECT * FROM :table_name ORDER BY :order DESC”之类的操作会产生 sql 错误,而上面的示例没有。 sql错误是: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的“用户”ORDER BY 'create_date'' 附近使用正确的语法
  • 这样的 return_all() 函数有什么意义?看起来您的表用作某种纯文本文件而不是数据库。为什么不让这个函数接受任意查询(和要绑定的参数)?
  • 您不能绑定 SQL 查询的结构元素,只能绑定 SQL 将操作的值。您不能绑定列名或表名。

标签: php mysql pdo sql-injection


【解决方案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;
}

【讨论】:

  • 它在那里,但没有格式化
  • @davidstrachan,嘿大卫,谢谢你的回答。这将是最安全的方法。我想写一些完全动态的东西,这样我就不需要在每个项目中都改变它,但我现在也意识到这种功能存在大量潜在的安全问题,所以肯定需要一点安全性。
猜你喜欢
  • 2014-11-07
  • 1970-01-01
  • 2013-03-07
  • 1970-01-01
  • 2014-11-03
  • 1970-01-01
  • 2016-03-08
  • 1970-01-01
相关资源
最近更新 更多