Защищен ли подготовленный оператор внутри хранимой процедуры от внедрения SQL? - PullRequest
1 голос
/ 28 августа 2011

В MySQL подготовленный оператор внутри хранимой процедуры безопасен от внедрения SQL? Смотрите пример ниже. Хранимой процедуре get_info передаются имя таблицы (pTbl) и предложение where (pWhere). pГде может быть много AND (например, fld1 = "a" AND fld2 = "b" AND ...). Вероятно, это не лучший способ сделать это, но мне нужно иметь динамический sql.

CREATE PROCEDURE get_info(pTbl VARCHAR(10), pWhere TEXT)
BEGIN
    SET @uSQL = CONCAT('SELECT info FROM ',pTbl,' WHERE ',pWhere);
    PREPARE ps FROM @uSQL;
    EXECUTE ps;
END$$

Я попытался вызвать хранимую процедуру, как показано ниже, с помощью MySQL Query Browser, но получил только ошибку, сообщающую, что в моем SQL есть синтаксическая ошибка.

CALL get_info('tbl','1=1;SELECT * FROM information_schema.TABLES;');

Если это помогает, хранимая процедура вызывается из PHP с использованием PDO, как показано ниже. $ tbl - это переменная $ _SESSION, а $ whr - это переменная $ _GET.

$s=$c->prepare("CALL get_info(?,?)");
$s->execute(array($tbl,$whr));

Безопасна ли эта хранимая процедура? Если нет, то как бы мне это ввести? Имеет ли значение, если я использую MySQL Query Browser с веб-страницы? Спасибо ...

Ответы [ 3 ]

2 голосов
/ 28 августа 2011

Да, это безопасно. (редактировать: нет, это не так)

Важно знать, когда текст SQL анализируется и преобразуется в семантическое дерево. Подготовленные заявления - это как раз то, что: заявления, которые подготовлены, просто ждут аргументов. Они хранятся на сервере, полностью скомпилированном с внутренним планом выполнения, с «дырами» для отсутствующих аргументов.

Вот почему вы получаете синтаксическую ошибку, вы пытаетесь установить целую часть WHERE в качестве аргумента; но это целое дерево выражений. Подготовленный оператор может иметь «дыры» только для элементов данных, но не для синтаксического текста.

Протокол, который передает аргументы, полностью безопасен в двоичном виде, независимо от того, что у вас есть в переменных аргумента, они будут отправляться как двоичные данные и использоваться только как данные, а не как часть команды SQL.

1012 * редактировать * по электронной почте Ой! Я только что заметил, что вы выполняете интерполяцию текста, но не в PHP, а в SQL. Это означает, что вы создаете команду SQL позже, используя внешние данные.

определенно небезопасно.

1 голос
/ 28 августа 2011

Каждый раз, когда вы интерполируете значение в утверждение, есть возможность внедрения. Процедура уязвима. Единственное общее ограничение с внедрением в процедуры и функции SQL заключается в том, что PREPARE работает с одним оператором. В этом конкретном случае вводимый текст следует за предложением WHERE в SELECT, в основном ограничивает атаки дополнительным выбором UNION, вызовом процедур и функций (хитро, но потенциально очень опасно) и дампом в файлы ( если определитель get_info имеет привилегию FILE).

В качестве примера попробуйте:

CALL get_info('tbl','1=0 UNION SELECT CONCAT(user, "@", host, " ", password) FROM mysql.user;');
1 голос
/ 28 августа 2011

Поскольку одно из значений приходит от пользователя, возможны некоторые формы SQL-инъекций;хотя можно выполнять только запросы SELECT, все же можно раскрыть информацию, передав 1=1 странице.Фактическая полезность информации, раскрываемой таким образом, может быть низкой, но она все же может иметь место.

...