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

2022-08-30 20:32:21

我和一位高声望的PHP家伙进行了这样的讨论:

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

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

<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 代码在客户端发送。


答案 1

你的建议确实是不正确的。

mysql_real_escape_string()不适用于动态表名;它旨在仅对字符串数据进行转义,仅用引号分隔。它不会转义反引号字符。这是一个小而关键的区别。

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

PDO 也不为动态表名称提供环境设置

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

我也没有完全意识到这一点,并且可能因为重复同样的坏建议而感到内疚,直到在SO上向我指出了这一点,也是由Shrapnel上校指出的。


答案 2

为了记录,下面是修复此孔的示例代码。

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

推荐