【发布时间】: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