PHP PDO:保护动态标识符免受SQL注入

时间:2016-03-03 11:28:09

标签: php mysql sql-injection

目前我正在研究一个简单工具的概念,以执行用PHP编写的一些“维护”数据库操作(删除/截断/复制表等)。

这必然要求SQL语句中的标识符是动态用户输入。虽然准备好的语句非常适合将SQL语句与任何比较值的用户输入分开,但它们并不适用于表名或列名等标识符。 (这意味着,我can't use准备了准备标识符的语句。)

保护动态标识符的常用方法是白名单,但这需要静态和已知的数据库结构。例如,我想实现像Copy table A and name it B这样的命令。这里有趣的部分是B

假设用户已通过身份验证并允许执行此操作,我该如何保护它免受SQL注入?这甚至可能吗?

我发现an approach建议在任何标识符中引用严重的重音符号(`):

$table_name        = 'origin_table'; // can be checked against existing tables
$copy_table_name   = 'user_input';
$quoted_table_name = '`' . str_replace( '`', '``', $copy_table_name ) . '`';
$sql_statement     = "CREATE TABLE {$quoted_table_name} LIKE {$table_name}";

这是否足以防止可能的SQL注入?

更新

PDO::quote()(在答案中提到)不是一种选择。它没有逃脱严重的重音(`):

$user_input = 'table`; TRUNCATE TABLE users --';
var_dump( $pdo->quote( $user_input ) );
//string(33) "'table`; TRUNCATE TABLE users --'"

更新2 PostgreSQL扩展具有完全符合该目的的功能:https://secure.php.net/manual/en/function.pg-escape-identifier.php

2 个答案:

答案 0 :(得分:0)

你总是希望转义`标识符,甚至是表名和字段名,因为明天它们可能是保留字并打破你的查询。只要您使用预备语句(PDO,mysqli或其他),您就可以了。请注意,PDO不允许转义表或字段名称。

你只需要对你的过滤机制进行细化,关于允许和不使用什么表名等。

顺便说一句:不要像你想做的那样:“CREATE TABLE {$ quoted_table_name} LIKE {$ table_name}”; ..用户准备好的语句与占位符(?,或:名称等)

修改 由于您需要保护标识符,我看到两种方式:

  1. 用(`)
  2. 包围它们
  3. 过滤&转义传入值(mysql_real_escape_string或更好)。过滤将包括删除任何不必要的字符(您可能只想允许字母[a-z] +或带数字的字母。

答案 1 :(得分:-1)

正如您所提到的,PDO的quote()函数可用于转义列名和数据。或者使用诸如CREATE TABLE之类的预准备语句?喜欢 ?然后只需执行查询。