目前我正在研究一个简单工具的概念,以执行一些用PHP编写的“维护”数据库操作(drop/truncate/copy tables等)。PHP PDO:保护针对SQL注入的动态标识符
这必然要求SQL语句中的标识符是动态用户输入。尽管预处理语句对于任何比较值的SQL语句与用户输入的分离都是完美的,但它们并不意味着用于表名或列名等标识符。 (也就是说,I 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
是的,但只要完整的字符串被认为是标识符,像'CHAR(96)'这样的函数不会被MySQL解释。 (编辑:我回答的评论已被删除) – David
大声思考:我会让用户在表单中输入表格和列名。现在,这些可以验证为无意义的字符和代码。然后可以很容易地检查它们与'mysql数据字典'的匹配。任何不匹配,然后错误。我还会有一个表格和/或列的“白名单”。从提供的信息中生成所需的SQL是一项相当简单的任务。即。想'查询建设者'? –
@RyanVincent谢谢,我会处理这些问题。一个最佳的解决方案将是像'TableCopier :: copyTables($ src,$ dest)'这样的方法。我肯定可以给这个方法写一个评论:«不要让它过分的价值!»。但是这并不能保护它不被使用,并在野外造成SQL漏洞。 – David