У меня есть приложение с PHP 5.3.29 и MySQL 5.6.35.
Я использовал SQLQUERY для выполнения инструкций SQL, затем изменил на PDO с подготовленными утверждениями, чтобы избежать SQL-i, но когда я тестирую свое приложение с ZAP 2.6.0, я могу подтвердить, что SQL-I все еще происходит, несмотря на использование «PDO» «и» подготовить «.
Я активировал общий журнал в MySQL и искал все операторы, которые были выполнены.
Мой код:
function cerrar_sesion($usuario) {
$pdo = new
PDO("mysql:"."host=".DB_SERVIDOR.";"."dbname=".DB_BASEDATOS,DB_USUARIO, DB_CLAVE);
$query = $pdo->prepare('UPDATE ADMIN_USUARIO SET USERID=\' \' WHERE C_USUARIO= :usuario');
$query->bindParam(':usuario',$usuario,PDO::PARAM_INT);
$query->execute();
$pdo = null;
.........
}
Проверяя журнал БД, я вижу, что параметр «C_USUARIO» изменился, из MySQL Log были извлечены следующие 3 строки:
227726 ОБНОВИТЬ запрос ADMIN_USUARIO УСТ. USERID = » ГДЕ C_USUARIO = ’54 / 2 ‘227730 Запрос ОБНОВИТЬ ADMIN_USUARIO УСТАНОВИТЬ USERID =’ ‘ГДЕ C_USUARIO =’ 108/2 ‘227732 Запрос ОБНОВИТЬ ОБНОВЛЕНИЕ ADMIN_USUARIO УСТАНОВИТЬ = ПОЛЬЗ. ‘
Обратите внимание, что значения для C_USUARIO не должны иметь «/ 2», который был введен ZAP
Я ожидал, что PDO предотвратит инъекцию, но это не тот случай, как я могу сделать это с помощью PDO?
Пожалуйста, помогите мне, я буду ценить это.
По умолчанию PDO «эмулирует» подготовленные операторы путем интерполяции связанных переменных в строку запроса SQL и последующего выполнения этого SQL напрямую, без использования параметров.
PDO применяет правильное экранирование, поскольку оно интерполирует ваши переменные в запросе, поэтому это безопасно в отношении внедрения SQL.
Если вы хотите реальные параметризованные запросы, отключите эмуляцию:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Увидеть http://php.net/manual/en/pdo.setattribute.php для дополнительной информации.
Если вы отключите эмуляцию, ваш журнал запросов MySQL покажет PREPARE и EXECUTE как отдельные шаги. Но MySQL также будет регистрировать полный запрос, включая значения параметров. Это также безопасно, это просто удобство, которое MySQL делает для ведения журнала, потому что полезно показывать запрос со значениями. Смотрите пример в моем ответе https://stackoverflow.com/a/210693/20860.
Других решений пока нет …