Все не так просто. Вы можете использовать связанные параметры вместо интерполяции переменных приложения в выражения 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
, и использование параметра будет интерпретироваться как первое - константная строка 'score'
, а не значение в столбце с именем score
.
Таким образом, существует множество случаев, когда вам нужно использовать динамический SQL и интерполировать переменные приложения в запрос, чтобы получить результаты, которые вы хочу. В таких случаях параметры запроса могут не помогу тебе. Вы по-прежнему должны быть бдительными и защищать код, чтобы предотвратить ошибки SQL-инъекций.
Никакая инфраструктура или библиотека доступа к данным не могут сделать эту работу за вас. Вы всегда можете создать строку SQL-запроса, содержащую ошибку SQL-инъекции, и сделать это до того, как библиотека доступа к данным увидит SQL-запрос. Так как же он должен знать, что намеренно, а в чем ошибка?
Вот методы для достижения безопасных запросов SQL:
Фильтр ввода. Отслеживайте любые данные переменных, которые вставляются в ваши SQL-запросы. Используйте входные фильтры , чтобы исключить недопустимые символы. Например, если вы ожидаете целое число, убедитесь, что ввод ограничен целым числом.
Отключить вывод. Выходными данными в этом контексте может быть SQL-запрос, который вы отправляете на сервер базы данных. Вы знаете, что можете использовать параметры запроса SQL для значений, но как насчет имени столбца? Вам нужна функция экранирования / заключения в кавычки для идентификаторов, как и старая mysql_real_escape_string ()
для строковых значений.
Проверка кода. Попросите кого-нибудь стать второй парой глаз и изучить ваш код SQL, чтобы помочь вам определить места, где вы пренебрегли двумя указанными выше методами.
Да. Использование подготовленного запроса приведет к экранированию параметров.
Когда вы привязываете параметры к подготовленному оператору, он автоматически экранирует данные, поэтому вы не должны экранировать его, прежде чем отправить его. Двойное побег - это обычно плохо. По крайней мере, позже он дает уродливые результаты с дополнительными экранированными символами.