Безопасно ли использовать связанные параметры в качестве пользовательских переменных в MySQL? - PullRequest
0 голосов
/ 01 мая 2018

ВЫПУСК

Я понимаю, что использование подготовленного оператора предотвращает внедрение, поскольку выполнение подготовленного оператора состоит из двух этапов: подготовка и выполнение .

ОК, но я не совсем понимаю, что происходит, если значение связанного параметра затем используется как определяемые пользователем переменные в MySQL.

Может ли изначально безопасный процесс связанных параметров использоваться для выполнения (и, следовательно, внедрения) в 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();

ПОЧЕМУ Я ХОЧУ ИСПОЛЬЗОВАТЬ ЭТОТ ПОДХОД?

Я использую это , чтобы избежать нескольких похожих именованных параметров, как в следующем примере, как

вы не можете использовать именованный маркер параметра с тем же именем больше, чем один раз в подготовленном операторе, если режим эмуляции не включен

из руководство . Это сложный вопрос для сложных запросов:

$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 голосов
/ 01 мая 2018

Да, вы можете предположить, что пользовательская переменная занимает место одного скалярного значения в запросе, как заполнитель связанного параметра. Это эффективная защита от внедрения SQL.

Подтверждение: попробуйте выполнить SQL-инъекцию, используя переменную пользователя.

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

SELECT * FROM Students WHERE name = @s;

Это НЕ сбросить таблицу. Это, вероятно, ничего не возвращает, потому что нет ученика с таким странным длинным именем (если вы не ходите в школу с Little Bobby Tables ).


Однако мне интересно, будет ли такой запрос:

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

Указывает, что field1, field2 и field3 действительно должны быть одним полем в дочерней таблице. Если вы ищете одно и то же значение в нескольких столбцах, это может быть повторяющаяся группа. Например, если это phone1, phone2, phone3, это многозначный атрибут, который должен храниться в одном столбце над несколькими строками в дочерней таблице. Тогда вы можете искать с одним параметром.

0 голосов
/ 01 мая 2018

В: Может ли изначально безопасный процесс связанных параметров использоваться для выполнения (и, следовательно, внедрения) в ШАГЕ 2?

A: Шаблон, показанный в коде вопроса, не открывает уязвимость SQL-инъекции.

Пользовательская переменная, используемая в качестве значения в выражении SQL (как показано в схеме в вопросе), рассматривается MySQL как значение . То есть MySQL не будет интерпретировать содержимое пользовательской переменной как часть текста SQL.

Чтобы это произошло, чтобы внедрить уязвимость SQL-инъекции, нам нужно было бы динамически создать текст SQL и подготовить / выполнить его с помощью операторов SQL MySQL PREPARE / EXECUTE.

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

Так что да. Использование пользовательской переменной (как показано в коде в вопросе) само по себе не представляет уязвимости SQL-инъекции.

(Но, чтобы не было недопонимания ... можно написать уязвимый код как с пользовательскими переменными, так и без них.)

...