在 MySQL 中将绑定参数用作用户定义的变量是否安全?
Is it safe to use Bound Parameters as User-Defined Variable in MySQL?
问题
我知道使用预处理语句可以防止注入 the prepared statement execution consists of two stages: prepare and execute。
好的,但如果绑定参数值随后在 MySQL.
中用作 User-Defined Variables,我真的不明白发生了什么
初始安全绑定参数过程是否可用于在步骤 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();
我为什么要使用这种方法?
我使用这个 来避免 多个相似的命名参数,如下例所示
you cannot use a named parameter marker of the same name more than
once in a prepared statement, unless emulation mode is on
来自 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 中执行(并因此注入)?
答:问题代码中显示的模式不会打开一个SQL注入漏洞。
在 SQL 语句中用作值的用户定义变量(如问题中的模式所示)被 MySQL 视为 value。也就是说,MySQL 不会将用户定义变量的内容解释为 SQL 文本的一部分。
要做到这一点,要引入 SQL 注入漏洞,我们需要动态构造 SQL 文本并使用 MySQL 获取 prepared/executed PREPARE
/EXECUTE
SQL 语句。
https://dev.mysql.com/doc/refman/5.7/en/prepare.html
所以,是的。使用用户定义的变量(如问题中的代码所示)本身不会引入 SQL 注入漏洞。
(但是,只是为了避免误解......有可能编写易受攻击的代码,无论是否有用户定义的变量。)
是的,您可以假设用户变量代替查询中的单个标量值,就像绑定参数占位符一样。这是针对 SQL 注入的有效保护。
证明:尝试使用用户变量执行 SQL 注入。
SET @s = 'Robert''; DROP TABLE Students;--';
SELECT * FROM Students WHERE name = @s;
这不会删除table。可能 returns 没什么,因为没有学生有那个奇怪的长名字(除非你用 Little Bobby Tables 上学)。
但是,我想知道是否有这样的查询:
SELECT ...
WHERE
table.field1 = @param1 OR
table.field2 = @param1 OR
table.field3 = @param1
表示 field1、field2 和 field3 确实应该是子项中的单个字段 table。如果您在多个列中搜索相同的值,它可能是一个重复组。例如,如果它是 phone1、phone2、phone3,那么这是一个多值属性,应该存储在子 table 的多行的一列中。然后你可以用一个参数搜索。
问题
我知道使用预处理语句可以防止注入 the prepared statement execution consists of two stages: prepare and execute。
好的,但如果绑定参数值随后在 MySQL.
中用作 User-Defined Variables,我真的不明白发生了什么初始安全绑定参数过程是否可用于在步骤 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();
我为什么要使用这种方法?
我使用这个 来避免 多个相似的命名参数,如下例所示
you cannot use a named parameter marker of the same name more than once in a prepared statement, unless emulation mode is on
来自 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 中执行(并因此注入)?
答:问题代码中显示的模式不会打开一个SQL注入漏洞。
在 SQL 语句中用作值的用户定义变量(如问题中的模式所示)被 MySQL 视为 value。也就是说,MySQL 不会将用户定义变量的内容解释为 SQL 文本的一部分。
要做到这一点,要引入 SQL 注入漏洞,我们需要动态构造 SQL 文本并使用 MySQL 获取 prepared/executed PREPARE
/EXECUTE
SQL 语句。
https://dev.mysql.com/doc/refman/5.7/en/prepare.html
所以,是的。使用用户定义的变量(如问题中的代码所示)本身不会引入 SQL 注入漏洞。
(但是,只是为了避免误解......有可能编写易受攻击的代码,无论是否有用户定义的变量。)
是的,您可以假设用户变量代替查询中的单个标量值,就像绑定参数占位符一样。这是针对 SQL 注入的有效保护。
证明:尝试使用用户变量执行 SQL 注入。
SET @s = 'Robert''; DROP TABLE Students;--';
SELECT * FROM Students WHERE name = @s;
这不会删除table。可能 returns 没什么,因为没有学生有那个奇怪的长名字(除非你用 Little Bobby Tables 上学)。
但是,我想知道是否有这样的查询:
SELECT ...
WHERE
table.field1 = @param1 OR
table.field2 = @param1 OR
table.field3 = @param1
表示 field1、field2 和 field3 确实应该是子项中的单个字段 table。如果您在多个列中搜索相同的值,它可能是一个重复组。例如,如果它是 phone1、phone2、phone3,那么这是一个多值属性,应该存储在子 table 的多行的一列中。然后你可以用一个参数搜索。