使用动态加载的表和数据库名称在查询中避免SQL注入

时间:2013-05-08 16:36:30

标签: mysql pdo prepared-statement sql-injection code-injection

我正在开发一个系统来以非常简单的方式管理数据库中的一些表。

系统首先使用Ajax加载用户可以查看和管理的数据库。然后加载该数据库中的表,然后加载该表的数据。

我有这样的事情:

$.ajax({
    url : "myUrl.php",
    data : {
        db : $dbSelector.val(),
        table : tableToLoad
    },
    success : function (json) { /* Some cool stuff here */ }
});

我发现当参数是db名称,表或列时你不能使用参数化查询,所以我不能这样做:

<?php
$query = "SELECT * FROM :db.:table";
$st = $pdo->prepare($query);
$st->execute(
    array(
        "db"=>$db, 
        "table" => $table
    )
);
$rows = $st->fetchAll(PDO::FETCH_OBJ);

我无法使用mysql_或mysqli_过滤因为我们没有安装它。

2 个答案:

答案 0 :(得分:1)

您可以使用:

$db = substr($dbh->quote($db), 1, -1);

或只删除所有非字母数字字符:

$db = preg_replace('/\W/', '', $db);

答案 1 :(得分:1)

接受的答案以及它所指的人工评论是一个致命的错误。

PDO :: quote与标识符无关,根本不应与它们一起使用。
从输出中删除引号使得它实际上是对SQL注入开放。

巧妙的PDO::quote()函数的关键在于产生正确的字符串文字。这意味着引用一个字符串并转义内部的引号,如果有的话。与仅执行部分格式化的mysql_real_escape_string不同,这是处理字符串的唯一正确方法 并且剥夺这个功能的一个职责实际上会导致一个简单的注入。

永远不应该使用

PDO::quote()来格式化标识符。他们需要totally different formatting.