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

Joh*_*ica 20 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());
Run Code Online (Sandbox Code Playgroud)

进入这个

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

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

Pek*_*ica 39

你的建议确实不正确.

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

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

PDO 也不为动态表名提供卫生设施.

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

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

  • +1优秀的答案.我今天肯定倾向于新的东西! (6认同)
  • +1这是我在PDO中长期遗漏的东西.一个'PDO->引用(...,PDO :: PARAM_IDENTIFIER)`或类似的东西.这通常会削弱PDO的跨数据库方法,因为不同的数据库有不同的引用和逃避.在MySQL中,你经常使用反引号,```只是`ANSI`模式中的标识符引用,但另一方面在其他DBMS中```是要走的路.哼,哼,哼哼:) (3认同)

Joh*_*ica 5

为了记录,这里是修复这个洞的示例代码.

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