Насколько prepare и execute обеспечивают безопасность sql-запроса от инъекции?

Используем PDO. Насколько безопасно использование полученных от пользователя данных для sql запроса с использованием prepare и execute с точки зрения возможной sql-инъекции?

Условный пример кода:
$query = $db->prepare('SELECT * FROM posts WHERE id = ?');
$query->execute([$_GET['id']);
  • Вопрос задан
  • 4108 просмотров
Пригласить эксперта
Ответы на вопрос 6
FanatPHP
@FanatPHP
Чебуратор тега РНР
Вообще, вопрос звучит довольно странно. "Можно ли применять автомобиль для езды?" "Годятся ли деньги для оплаты товаров?", "Безопасны ли подготовленные выражения с точки зрения защиты от инъекций?".
Собственно, если это их основное предназначение - то наверное, не обеспечивай они защиту, то были бы бесполезны чуть более, чем полностью?

Смысл подготовленных выражений в том, чтобы решить 3 задачи при формировании динамического запроса:
1. чтобы вставляемый в запрос литерал был отформатирован корректно
2. Чтобы форматирование было обязательным
3. Чтобы оно производилось как можно ближе к фактическому исполнению запроса.

Благодаря этим трем пунктам обеспечивается гарантированная защита даже с учетом человеческого фактора.

Так что да - если ЛЮБАЯ переменная попадает в запрос только через плейсхолдер - этот запрос безопасен. Другое дело, что в реальной жизни так не выходит, и переменные в запрос добавлять приходится. Как поступать в таких случаях, я описал в специальной статье

Ну и напоследок стоит упомянуть о том, что режимов работы у ПДО два: "настоящие" подготовленные выражения и эмуляция. В первом случае запрос исполняется в два этапа - сначала отправляется на серевер БД запрос с плейсхолдерами (знаками вопроса), а потом, следующим пакетом - данные для него. Этот режим также удобен если нам надо выполнить много однотипных запросов, позволяя сэкономить пару наносекунд. По умолчанию же ПДО только эмулирует этот режим, отправляя запрос в одну ходку, подставляя значения прямо в запрос. Но поскольку он форматирует их корректно, то никакой опасности опять же нету

Ну и под конец можно упомянуть редчайший случай, раздуваемый истеричками типа Шифлетта или Феррары - если вы китаец, и используете кодировку GBK (или одну из пары других, столько же часто используемых), то надо не забыть выставить кодировку соединения именно в DSN и только в DSN. Потому что если использовать по привычке SET NAMES, то в режиме эмуляции инъекция будет возможна. То есть, ситуация, когда инъекция через ? плейсхолдер возможна - она существует. Но для этого должны совпасть три фактора:
- вы должны быть китайцем и использовать кодировку GBK
- кодировка должна быть задана не в DSN
- режим эмуляции должен быть включён
Ответ написан
Lerg
@Lerg
Defold, Corona, Lua, GameDev
Ещё советую явно приводить к численным типам в запросах intval(), floatval() и обрезать длинные строки (чтобы мегабайты/гигабайты нельзя было передавать).
Далее уже идут только уязвимости обусловленные плохим дизайном базы/сервиса (получение привелегий, подмена параметров).
Ответ написан
miraage
@miraage
Старый прогер
Да, так безопасно.
Как вариант :
$query = $db->prepare('SELECT * FROM posts WHERE id = :id');
$query->bindValue(':id', $_GET['id'], PDO::PARAM_INT);
Ответ написан
Комментировать
deadbyelpy
@deadbyelpy
веб-шмеб
При подготовленных выражениях спасают от уязвимостей первого и второго порядка. Это в случае если sql не формируется динамически, а таком случае только первого.
По простому, защищает от всех возможных sql инъекций, ddos, и прочих нагрузочных запросов.
У нас на больших проектах(php) очистка проходит именно так, пока проблем с безопасностью не было.
Ответ написан
В вашем примере безопасность на уровне экранирования кавычек и спецсимволов. На практике это даёт хорошую защиту, но не полную, т.к. хакер может использовать особенности запроса и хитрые комбинации спецсимволов.
Пример, который привёл Miraage даёт защиту от комбинаций спецсимволов, но не защищает от неправильной структуры БД.
Ответ написан
GM2mars
@GM2mars
Ещё не стоит забывать, что prepare запросы не экранируют теги (возможно и javascript, но не проверял). Просто почему-то был уверен что html теги тоже автоматически экранируются, пока не проверил ))
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы