Почему использование подготовленного оператора mysql более безопасно, чем использование общих функций эвакуации?

В другом вопросе есть комментарий, в котором говорится следующее:

«Когда дело доходит до запросов к базе данных, всегда старайтесь использовать подготовленные параметризованные запросы. Библиотеки mysqli и PDO поддерживают это. Это бесконечно безопаснее, чем использование функций escaping, таких как mysql_real_escape_string».

Источник

Итак, я хочу спросить: почему подготовленные параметризованные запросы более безопасны?

Важным моментом, по которому я думаю, что люди здесь не хватает, является то, что с базой данных, которая поддерживает параметризованные запросы, не существует «ускользания», о котором можно беспокоиться. Механизм базы данных не объединяет связанные переменные в оператор SQL, а затем анализирует все это; Связанные переменные сохраняются отдельно и никогда не анализируются как общий оператор SQL.

Вот откуда берется безопасность и скорость. Механизм базы данных знает, что заполнитель содержит только данные, поэтому он никогда не анализируется как полный оператор SQL. Ускорение происходит, когда вы готовите заявление один раз, а затем выполняете его много раз; канонический пример – вставка нескольких записей в одну и ту же таблицу. В этом случае движок базы данных должен анализировать, оптимизировать и т. Д. Только один раз.

Теперь один из них содержит библиотеки абстракции базы данных. Иногда они подделывают его, просто вставляя связанные переменные в оператор SQL с соответствующим экранированием. Тем не менее, это лучше, чем делать это самостоятельно.

Во-первых, вы покидаете экранирование опасных символов в базе данных, что намного безопаснее, чем вы, человек.

… он не забудет бежать или пропустить какие-либо специальные символы, которые могут быть использованы для инъекции какого-то вредоносного SQL. Не говоря уже о том, что вы можете получить повышение производительности для загрузки!

Я не очень разбираюсь в безопасности, но вот объяснение, которое, я надеюсь, поможет вам:

Допустим, у вас есть заявление вроде:

выберите [integer] из mydb

Притворяйтесь, когда вы его готовите, инструкция сводится к байтам в нашей воображаемой реализации sql.

01 00 00 23 Opcode for select Prepared bytes number of "mydb" for your integer 

Теперь, когда вы выполните, вы введете номер в пространство, зарезервированное для вашего подготовленного оператора.

Сравните это с тем, если вы просто используете escape, вы можете вставить туда столько тарабарщин и, возможно, привести к переполнению памяти или к какой-нибудь команде bizzare sql, которую они забыли избежать.

Потому что с подготовленными заявлениями вы не можете забыть избежать содержимого. Таким образом, нет никакого способа ввести неуверенность.

mysql_real_escape_string так же безопасен, как и подготовленные инструкции, если вы не забудете использовать mysql_real_escape_string каждый раз, когда вы вызываете mysql_query, но его легко забыть.

Эта функция небезопасна из-за этого использования http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string . Вот почему подготовленные заявления предпочтительнее, и это также улучшает производительность.

Подготовленные заявления решают фундаментальную проблему безопасности приложений, которая несовместима с санацией данных: они приводят к полному разделению данных и инструкций . Когда эти два путаются, результатом является отсутствие безопасности. Это справедливо для SQL-инъекций, а также для переполнения буфера.

(Есть другие способы быть небезопасными.)

В лучшем случае это может быть не так, но это, по крайней мере, безопасно; и зачем рисковать?