简体   繁体   English

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

[英]Is it safe to use Bound Parameters as User-Defined Variable in MySQL?

THE ISSUE 问题

I understand that using prepared statement prevents injection as the prepared statement execution consists of two stages: prepare and execute . 我知道使用预处理语句可以防止注入,因为预处理语句的执行包括两个阶段:prepare和execute

OK, but I do not really get what is going on if a bound parameter value is then used as a User-Defined Variables in MySQL. 可以,但是如果绑定参数值随后用作MySQL中的用户定义变量 ,我将无法真正了解情况。

Is the initially safe bound parameters process can be used for execution (and therefore injection) in STEP 2 ? 是否可以在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();

WHY DO I WANT TO USE THIS APPROACH ? 我为什么要使用此方法?

I use this to avoid multiple similar named parameters like in the following example hereafter as 我用它来避免多个类似的命名参数,如以下示例中所示:

you cannot use a named parameter marker of the same name more than once in a prepared statement, unless emulation mode is on 您不能在准备好的语句中多次使用相同名称的命名参数标记,除非启用了仿真模式

from manual . 手册 It's a mess to maintain for complex queries: 维护复杂的查询很麻烦:

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

Yes, you can assume that a user variable takes the place of a single scalar value in a query, just like a bound parameter placeholder. 是的,您可以假设用户变量在查询中代替单个标量值,就像绑定参数占位符一样。 It's an effective protection against SQL injection. 这是防止SQL注入的有效保护。

Proof: Try to perform an SQL injection using a user variable. 证明:尝试使用用户变量执行SQL注入。

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

SELECT * FROM Students WHERE name = @s;

This does NOT drop the table. 删除该表。 It probably returns nothing, because there is no student with that strange, long name (unless you go to school with Little Bobby Tables ). 它可能不会返回任何内容,因为没有一个名字那么古怪的学生(除非您带着Little Bobby Tables上学)。


However, I wonder if a query like this: 但是,我想知道是否这样的查询:

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

Indicates that field1, field2, and field3 should really be a single field in a child table. 指示field1,field2和field3实际上应该是子表中的单个字段。 If you're searching for the same value in multiple columns, it could be a repeating group. 如果要在多列中搜索相同的值,则它可能是重复的组。 For example, if it's phone1, phone2, phone3, that's a multi-valued attribute that should be stored in one column over multiple rows in a child table. 例如,如果它是phone1,phone2,phone3,则这是一个多值属性,应存储在子表中多行的一列中。 Then you can search with a single parameter. 然后,您可以使用单个参数进行搜索。

Q: Is the initially safe bound parameters process can be used for execution (and therefore injection) in STEP 2 ? 问:最初安全的绑定参数过程是否可以在STEP 2中用于执行(并因此用于注入)?

A: The pattern shown in the code in the question does not open up a SQL Injection vulnerability. 答:问题代码中显示的模式不会打开SQL注入漏洞。

A user defined-variable used as a value in a SQL statement (as shown in the pattern in the question) is seen by MySQL as a value . 用户将定义的变量用作SQL语句中的值(如问题中的模式所示),MySQL会将其视为value That is, MySQL will not interpret the contents of the user-defined variable as part of the SQL text. 也就是说,MySQL不会将用户定义变量的内容解释为SQL文本的一部分。

To get that to happen, to introduce a SQL Injection vulnerability, we would would need to dynamically construct SQL text and get that prepared/executed with the MySQL PREPARE / EXECUTE SQL statements. 为了实现这一点,引入一个SQL注入漏洞,我们将需要动态构造SQL文本,并使用MySQL PREPARE / EXECUTE SQL语句来准备/执行该文本。

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

So, yes. 所以,是的。 Using a user-defined variable (as shown in the code in the question) does not in itself introduce SQL Injection vulnerability. 使用用户定义的变量(如问题中的代码所示)本身并不引入SQL注入漏洞。

(But, just so there is no misunderstanding... it is possible to write vulnerable code, both with and without user-defined variables.) (但是,这样就不会造成误解……可以编写有或没有用户定义变量的易受攻击的代码。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM