Идея очень проста - запрос и данные отправляются на сервер базы данных отдельно .
Вот и все.
Корень проблемы внедрения SQL смешивание кода и данных.
Фактически, наш SQL-запрос легитимная программа .И мы создаем такую программу динамически, добавляя некоторые данные на лету.Таким образом, эти данные могут мешать программному коду и даже изменять его, как показывает каждый пример SQL-инъекции (все примеры в PHP / Mysql):
$expected_data = 1;
$query = "SELECT * FROM users where id=$expected_data";
будет производить регулярныйзапрос
SELECT * FROM users where id=1
, в то время как этот код
$spoiled_data = "1; DROP TABLE users;"
$query = "SELECT * FROM users where id=$spoiled_data";
создаст вредоносную последовательность
SELECT * FROM users where id=1; DROP TABLE users;
Это работает, потому что мы добавляем данные непосредственно в тело программы иона становится частью программы, поэтому данные могут изменить программу, и в зависимости от переданных данных у нас будет либо обычный вывод, либо таблица users
.
, тогда как в случаеподготовленные заявления, мы не изменяем нашу программу, она остается неизменной
В этом все дело.
Сначала мы отправляем программу на сервер
$db->prepare("SELECT * FROM users where id=?");
, где данные заменяются некоторой переменной , называемой параметром или заполнителем.
Обратите внимание, что тот же запрос отправляется на сервер, без каких-либо данных в нем!И затем мы отправляем данные с помощью второго запроса, по существу отделенного от самого запроса:
$db->execute($data);
, поэтому он не может изменить нашу программу и причинить какой-либо вред.
Довольно просто - не так ли?
Однако стоит отметить, что не каждый раз вы используете заполнитель, он обрабатывается как подготовленный оператор .
Заполнитель - это общая идея для замены фактических данных переменной для будущей обработки (см., Например, printf()
), в то время как подготовленный оператор является единственным его подмножеством.
Существуют случаи (в частности, PDO в PHP может это сделать), когда подготовленный оператор может быть эмулирован, и запрос фактически составляется вместе с данными и отправляется на сервер в одном запросе.Но важно понимать, что этот подход одинаково безопасен , потому что каждый бит данных правильно отформатирован в соответствии с его типом , и, следовательно, ничего плохого не может произойти.
Единственное, что я должен добавить, которое всегда опускается в каждом руководстве:
Подготовленные операторы могут защитить только данные , но не может защитить саму программу .
Итак, как только мы добавим, скажем, динамический идентификатор - например, имя поля, подготовленные операторы не могут нам помочь.Я недавно объяснил этот вопрос , поэтому я не буду повторяться.