在mysql中使用绑定参数作为用户定义变量安全吗?

ut6juiuv  于 2021-06-21  发布在  Mysql
关注(0)|答案(2)|浏览(389)

问题

我知道使用prepared语句可以防止注入,因为prepared语句的执行包括两个阶段:prepare和execute。
好的,但是如果一个绑定参数值被用作mysql中的用户定义变量,我并没有真正了解到底发生了什么。
在步骤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();

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

我使用它来避免多个类似的命名参数,如下例所示
除非启用了仿真模式,否则不能在准备好的语句中多次使用同名的命名参数标记
从手动。对于复杂的查询,维护起来很混乱:

$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);
1u4esq0p

1u4esq0p1#

问:在第2步中,最初的安全边界参数进程是否可以用于执行(从而注入)?
答:问题代码中显示的模式不会打开sql注入漏洞。
在sql语句中用作值的用户定义变量(如问题中的模式所示)被mysql视为值。也就是说,mysql不会将用户定义变量的内容解释为sql文本的一部分。
要做到这一点,要引入sql注入漏洞,我们需要动态构造sql文本,并使用mysql准备/执行该文本 PREPARE / EXECUTE sql语句。
https://dev.mysql.com/doc/refman/5.7/en/prepare.html
所以,是的。使用用户定义的变量(如问题代码所示)本身不会引入sql注入漏洞。
(但是,为了避免误解。。。可以编写易受攻击的代码,包括有或没有用户定义的变量。)

vx6bjr1n

vx6bjr1n2#

是的,您可以假设用户变量代替查询中的单个标量值,就像绑定参数占位符一样。它可以有效地防止sql注入。
证明:尝试使用用户变量执行sql注入。

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

SELECT * FROM Students WHERE name = @s;

这不会让table掉下来。它可能什么也不返回,因为没有一个学生有那个奇怪的,长的名字(除非你去学校的小鲍比表)。
但是,我想知道这样的问题:

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

指示字段1、字段2和字段3实际上应该是子表中的单个字段。如果在多个列中搜索相同的值,则可能是重复组。例如,如果是phone1、phone2、phone3,那么这是一个多值属性,应该存储在子表中多行的一列中。然后可以使用单个参数进行搜索。

相关问题