Насколько 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 теги тоже автоматически экранируются, пока не проверил ))
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
YCLIENTS Москва
от 200 000 до 350 000 ₽
Ведисофт Екатеринбург
от 25 000 ₽
ИТЦ Аусферр Магнитогорск
от 100 000 до 160 000 ₽