В MySQL подготовленный оператор внутри хранимой процедуры безопасен от SQL-инъекции? См. Пример ниже. Хранимой процедуре get_info передается имя таблицы (pTbl) и предложение where (pWhere). pWhere может иметь много 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 или с веб-страницы? Спасибо...

1
Txoov 28 Авг 2011 в 14:26

3 ответа

Лучший ответ

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

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

CALL get_info('tbl','1=0 UNION SELECT CONCAT(user, "@", host, " ", password) FROM mysql.user;');
1
outis 28 Авг 2011 в 11:31

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

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

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

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

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

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

2
Javier 28 Авг 2011 в 11:03

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

1
Ignacio Vazquez-Abrams 28 Авг 2011 в 10:57