如何使用动态表名防止SQL注入?

时间:2011-04-27 23:16:37

标签: php sql-injection

我与一位声誉很高的人PHP进行了讨论:

  

PDO在这里没用。以及mysql_real_escape_string。   质量极差。

这当然很酷,但老实说我不知道​​建议使用mysql_real_escape_string或PDO修复此代码有什么问题:

<script type="text/javascript">
    var layer;

    window.location.href = "example3.php?layer="+ layer;

    <?php
        //Make a MySQL connection
        $query = "SELECT Category, COUNT(BUSNAME)
          FROM ".$_GET['layer']." GROUP BY Category";
        $result = mysql_query($query) or die(mysql_error());

进入这个

$layer = mysql_real_escape_string($_GET['layer']);
$query = "SELECT Category, COUNT(BUSNAME)
FROM `".$layer."` GROUP BY Category";

,考虑到JavaScript代码发送到客户端。

3 个答案:

答案 0 :(得分:38)

你的建议确实不正确。

mysql_real_escape_string()不适用于动态表名;它旨在转义仅由引号分隔的字符串数据。它不会逃脱反击的角色。这是一个小而重要的区别。

所以我可以在这里插入一个SQL注入,我只需要使用结束反引号。

PDO does not provide sanitation for dynamic table names, either

这就是为什么不使用动态表名,或者必须将它们与有效值列表(如SHOW TABLES命令中的表列表进行比较)。

我也没有完全意识到这一点,并且可能会重复同样的错误建议,直到我在这里向我指出,也是由Shrapnel上校指出的。

答案 1 :(得分:5)

对于记录,这是修复此漏洞的示例代码。

$allowed_tables = array('table1', 'table2');
$clas = $_POST['clas'];
if (in_array($clas, $allowed_tables)) {
    $query = "SELECT * FROM `$clas`";
}

答案 2 :(得分:2)

为了回答如何实际修复代码:

'...FROM `' . str_replace('`', '``', $tableName) . '`...'

这会复制表名中的所有反引号(这就是MySQL中的转义)。

我不确定的一件事是,这是否是“编码安全”(如何正确地调用它?)。一个人通常建议mysql_real_escape_string而不是addslashes,因为前者考虑了MySQL连接的编码。也许这个问题也适用于此。