Исторически я всегда использовал
mysql_real_escape_string()
для всех входных данных, полученных от пользователей, которые заканчиваются касанием базы данных.
Теперь, когда я полностью перешел на MySQLi, и я использую подготовленные запросы со связанными параметрами, эффективно ли я удалил атаки SQL-инъекций?
Правильно ли я говорю, что мне больше не нужно
mysql_real_escape_string()?
Это мое понимание и основа моего проекта: http://sourceforge.net/projects/mysqldoneright/files/Base/MysqlDoneRight-0.23.tar.gz/download
Это не то, что я хочу ошибаться, хотя теперь, когда я его выпустил, это может повлиять и на других.
Все введенные пользователем данные теперь будут в bind_parms.
Запросы, представленные на этапе подготовки, являются статическими.
Это не так просто. Вы можете использовать привязанные параметры вместо интерполяции переменных приложения в выражения SQL вместо буквенных значений :
$sql = "SELECT * FROM MyTable WHERE id = ".$_GET["id"]; // not safe $sql = "SELECT * FROM MyTable WHERE id = ?"; // safe
Но что, если вам нужно сделать часть динамического запроса, кроме литерального значения?
$sql = "SELECT * FROM MyTable ORDER BY ".$_GET["sortcolumn"]; // not safe $sql = "SELECT * FROM MyTable ORDER BY ?"; // doesn't work!
Параметр всегда будет интерпретироваться как значение, а не идентификатор столбца. Вы можете запускать запрос с помощью ORDER BY 'score'
, который отличается от ORDER BY score
, а использование параметра будет интерпретироваться как первое – константа string 'score'
, а не значение в столбце с именем score
.
Таким образом, есть много случаев, когда вам нужно использовать динамический SQL и интерполировать переменные приложения в запрос, чтобы получить нужные результаты. В таких случаях параметры запроса не могут помочь вам. Вы все еще должны быть бдительными и защищать код, чтобы предотвратить ошибки SQL-инъекций.
Никакая инфраструктура или библиотека доступа к данным не могут выполнить эту работу для вас. Вы всегда можете построить строку запроса SQL, содержащую ошибку SQL-инъекции, и вы делаете это до того, как библиотека доступа к данным увидит SQL-запрос. Итак, как это должно знать, что преднамеренно и что является недостатком?
Вот методы для обеспечения безопасных SQL-запросов:
Вход фильтра. Отслеживайте любые переменные данные, которые вставляются в ваши SQL-запросы. Используйте фильтры ввода, чтобы вырезать незаконные символы. Например, если вы ожидаете целое число, убедитесь, что вход ограничен целым числом.
Выход выхода. Вывод в этом контексте может быть SQL-запросом, который вы отправляете на сервер базы данных. Вы знаете, что вы можете использовать параметры запроса SQL для значений, но как насчет имени столбца? Вам нужна функция экранирования / цитирования для идентификаторов, так же как старый mysql_real_escape_string()
для строковых значений.
Обзор кода. Попросите кого-нибудь быть второй парой глаз и перейдите по вашему SQL-коду, чтобы помочь вам определить места, где вы пренебрегали использованием вышеупомянутых двух методов.
Да. Использование подготовленного запроса позволит избежать параметров.
Когда вы привязываете параметры к подготовленному оператору, он автоматически вытесняет данные, поэтому вам не следует избегать его, прежде чем отправлять его. Двойное экранирование обычно плохое. По крайней мере, это приводит к уродливым результатам с дополнительными экранированными символами позже.