82

我已经多次使用 mysqli_stmt_bind_param 函数。但是,如果我将试图防止 SQL 注入的变量分开,我会遇到错误。

这是一些代码示例:

function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol )
{
    $statement = $mysqli->prepare("INSERT INTO " .$new_table . " VALUES (?,?,?,?,?,?,?);");
    mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
    $statement->execute();
}

是否可以以某种方式.$new_table.用另一个问号语句替换连接,创建另一个绑定参数语句,或者添加到现有的语句以防止 SQL 注入?

像这样或这样的某种形式:

function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol )
{    
    $statement = $mysqli->prepare("INSERT INTO (?) VALUES (?,?,?,?,?,?,?);");
    mysqli_stmt_bind_param( $statment, 'ssssisss', $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
    $statement->execute();
}
4

2 回答 2

98

对您的问题的简短回答是“不”。

在最严格的意义上,在数据库级别,准备好的语句只允许为 SQL 语句的“值”位绑定参数。

对此的一种思考方式是“可以在语句的运行时执行时替换而不改变其含义的东西”。表名不是那些运行时值之一,因为它决定了 SQL 语句本身的有效性(即,哪些列名是有效的)并且在执行时更改它可能会改变 SQL 语句是否有效。

在稍高的级别上,即使在模拟准备好的语句参数替换而不是实际将准备好的语句发送到数据库的数据库接口中,例如 PDO,这可能允许您在任何地方使用占位符(因为占位符在被发送到之前被替换)那些系统中的数据库),表占位符的值将是一个字符串,并包含在发送到数据库的 SQL 中,因此SELECT * FROM ?使用mytableas 参数实际上最终会发送SELECT * FROM 'mytable'到数据库,这是无效的 SQL。

你最好的选择就是继续

SELECT * FROM {$mytable}

但是如果来自用户输入,您绝对应该有一个您首先检查的表的白名单。$mytable

于 2012-07-04T11:05:06.180 回答
1

尝试创建“数据库”时也适用相同的规则。

您不能使用准备好的语句来绑定数据库。

IE:

CREATE DATABASE IF NOT EXISTS ?

不管用。请改用安全列表。

于 2018-11-08T15:08:09.460 回答