Mike Casan Ballester
Mike Casan Ballester

Reputation: 1770

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.

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.

Is the initially safe bound parameters process can be used for execution (and therefore injection) in 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);

Upvotes: 3

Views: 338

Answers (2)

Bill Karwin
Bill Karwin

Reputation: 562651

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.

Proof: Try to perform an SQL injection using a user variable.

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).


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. 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. Then you can search with a single parameter.

Upvotes: 5

spencer7593
spencer7593

Reputation: 108460

Q: Is the initially safe bound parameters process can be used for execution (and therefore injection) in STEP 2 ?

A: The pattern shown in the code in the question does not open up a SQL Injection vulnerability.

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. That is, MySQL will not interpret the contents of the user-defined variable as part of the SQL text.

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.

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.

(But, just so there is no misunderstanding... it is possible to write vulnerable code, both with and without user-defined variables.)

Upvotes: 2

Related Questions