Как именно плейсхолдеры (подготовленные выражения) защищают от sql-инъекций?

Доброго дня.
Собственно, сабж. Прочитав описание подготовленных выражений из документации на php.net, где ничего не говорится о самой реализации, я порой даже опасаюсь использовать подготовленные запросы: мне приходится верить на слово авторитетным разработчикам, авторам статей на хабре и той же документации (в таких случаях я составляю "белые списки с именами полей и возможными значениями, что порой существенно усложняет реализацию). Очевидно, что данный подход при написании запросов - едва ли не единственно верный, сам уже давно использую лишь его, однако полного понимания до сих пор нет. Что именно происходит с переданными в ту же PDO параметрами там, внутри, в момент подготовки и выполнения запроса?

Заранее спасибо!
  • Вопрос задан
  • 4607 просмотров
Решения вопроса 2
Подготовленные выражения защищают от SQL-инъекций тем, что отделяют синтаксис запроса от значений параметров запроса. Суть любой SQL-инъекции - изменить синтаксис (текст, если угодно) запроса тем или иным образом. Если вы передаете текст запроса и параметры отдельно, не будет никакой возможности повлиять на синтаксис запроса из параметра запроса.

В случае поддержки со стороны СУБД, подтоговленные выражения PHP должны использовать возможности СУБД и передавать ей сначала текст запроса для компиляции, а уже потом, отдельно - параметры запроса.

Теоретически, проблемы могут быть только в случае, если prepared statements не поддерживаются самой СУБД и эмулируются PDO (т.е. на стороне скрипта, а не БД). Тогда косяки в реализации сборки конечного запроса могут сказаться на безопасности. В случае поддержки со стороны СУБД "реализовывать" просто напросто нечего - вы защищены от инъекций не за счет экранирования всего и вся, а за счет правильного подхода - никогда не смешивать сам запрос и его параметры.

Насколько мне известно, mysql уже давным-давно поддерживает prepared statements, поэтому не вижу смысла бояться их использовать. А даже если б это было не так, вероятность в том, что при ручной сборке запроса накосячите ВЫ - гораздо выше.

UPDATE: полезнейший коммент на странице php.net/manual/ru/pdo.prepare.php:
With PDO_MYSQL you need to remember about the PDO::ATTR_EMULATE_PREPARES option.

The default value is TRUE, like
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,true);

This means that no prepared statement is created with $dbh->prepare() call. With exec() call PDO replaces the placeholders with values itself and sends MySQL a generic query string.

The first consequence is that the call $dbh->prepare('garbage');
reports no error. You will get an SQL error during the $dbh->exec() call.
The second one is the SQL injection risk in special cases, like using a placeholder for the table name.

The reason for emulation is a poor performance of MySQL with prepared statements. Emulation works significantly faster.

Так что да, есть доля внезапности в поведении PDO. Я думаю стоит порыть инфы о настройке PDO::ATTR_EMULATE_PREPARES. Я считаю, что включать по-дефолту именно эмуляцию - это в высшей степени недальновидное решение. Проблемы MySQL затыкаются на стороне стандартной библиотеки языка....
Ответ написан
@mistergonza
PHP6 evangelist
За счет автоматического экранирования параметров.
php.net/manual/ru/pdo.prepared-statements.php
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Верьте только своему regex-выражению перед любой обработкой всех входных данных.
Ответ написан
trevoga_su
@trevoga_su
https://habrahabr.ru/post/148701/
советую прочитать эту статью от корки до корки
там все описано
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы