在MySQL中使用绑定参数作为用户定义变量是否安全?

时间:2018-05-01 15:13:12

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

问题

据我所知,使用预准备语句可以防止注入为the prepared statement execution consists of two stages: prepare and execute

好的,但如果绑定的参数值在MySQL中用作User-Defined Variables,我真的不知道发生了什么。

初始安全绑定参数过程是否可用于在STEP 2中执行(因此注入)?

// The user input that may be the target for injection
$userInput = "input";

// STEP 1 -------------------
$q = "SET @param1 = :param1;";  

// Execute query to set mysql user-defined variables
$param = [
'param1'    => $userInput
];

$stmt = $pdo->prepare($q);
$stmt->execute($param);


// STEP 2 -------------------
// Query DB with User-Defined Variables
$q = "
SELECT ...
WHERE 
table.field1 = @param1 OR
table.field2 = @param1 OR
table.field3 = @param1
";

// Query
$stmt = $pdo->query($q);


// STEP 3 -------------------   
// Fetch Data
$row = $stmt->fetch();

我为什么要使用这种方法?

我使用来避免多个类似的命名参数,如下面的示例所示

  

您不能使用同名的命名参数标记   一旦在准备好的声明中,除非仿真模式打开

来自manual

。维护复杂的查询很麻烦:

$q = "
SELECT ...
WHERE 
table.field1 = :param1_1 OR
table.field2 = :param1_2 OR
table.field3 = :param1_2
";

$param = [
'param1_1'  => $userInput
'param1_2'  => $userInput
'param1_3'  => $userInput
];

$stmt = $pdo->prepare($q);
$stmt->execute($param);

2 个答案:

答案 0 :(得分:3)

是的,您可以假设用户变量取代查询中的单个标量值,就像绑定参数占位符一样。它是对SQL注入的有效保护。

证明:尝试使用用户变量执行SQL注入。

SET @s = 'Robert''; DROP TABLE Students;--';

SELECT * FROM Students WHERE name = @s;

NOT 删除表格。它可能什么也没有返回,因为没有学生有这个奇怪的长名称(除非你带着Little Bobby Tables去学校。)

但是,我想知道是否有这样的查询:

SELECT ...
WHERE 
table.field1 = @param1 OR
table.field2 = @param1 OR
table.field3 = @param1

表示field1,field2和field3应该是子表中的单个字段。如果您在多列中搜索相同的值,则可能是重复组。例如,如果是phone1,phone2,phone3,则这是一个多值属性,应该存储在子表中多行的一列中。然后,您可以使用单个参数进行搜索。

答案 1 :(得分:2)

问:初始安全绑定参数过程是否可用于在STEP 2中执行(以及注入)?

答:问题代码中显示的模式打开SQL注入漏洞。

用作SQL语句中的值的用户定义变量(如问题中的模式所示)被MySQL视为。也就是说,MySQL不会将用户定义变量的内容解释为SQL文本的一部分。

为了实现这一点,为了引入SQL注入漏洞,我们需要动态构造SQL文本并使用MySQL PREPARE / EXECUTE SQL语句准备/执行。

https://dev.mysql.com/doc/refman/5.7/en/prepare.html

所以,是的。使用用户定义的变量(如问题中的代码所示)本身并不会引入SQL Injection漏洞。

(但是,这样就没有误解......有可能编写易受攻击的代码,无论是否有用户定义的变量。)