Как предотвратить SQL-инъекции в PHP?

Способ 1. Запросы и параметрами

Используйте так называемые готовые выражения (prepared statements) и запросы с параметрами (параметризованные запросы — parameterized queries). MySQL поддерживает такой способ передачи запросов, при котором сами команды SQL посылаются и обрабатываются сервером отдельно от параметров.

Если Вы используете PHP Dara Objects, Вы можете работать с готовыми выражениями как-то так:

$preparedStatement = $db->prepare(''SELECT * FROM employees WHERE name = :name'');
$preparedStatement->execute(array('':name'' => $name));
$rows = $preparedStatement->fetchAll();

Подробнее смотрите в документации по PDO. Класс mysqli также позволяет использовать запросы с параметрами.

Что же происходит в этом случае при передачи SQL-выражения в базу данных? Оно анализируется и обрабатывается. С помощью специфических параметров (типа «?» или «:name» в примере выше) Вы указываете движку базы данных, что именно необходимо отфильтровать. Затем, когда Вы вызываете команду «выполнить», готовое выражение объединяется со значением параметров, которое Вы задали.

Важный момент здесь — это то, что значения параметров объединяются с откомпилированными выражениями, а не из SQL-строкой. SQL-инъекции сводятся к внедрению вредоносного фрагмента в сам SQL-запрос, который создаётся перед отправкой в базу данных. Так что отделение команд SQL от параметров сводит к минимуму риск возникновения непредвиденных ситуаций. Любые параметры, которые Вы посылаете, используя готовые выражения, будут восприниматься как строка (несмотря на то, что база данных может проводить над ними необходимую оптимизацию). В примере выше, если переменная $name будет содержать

''Sarah''; DELETE * FROM employees

, то результат будет просто поиском по строке

"''Sarah''; DELETE * FROM employees"

, и Вы, естественно, в итоге не останетесь с пустой таблицей.

Ещё одна польза от использования готовых выражений — это то, что Вы можете удобно выполнять одни и те же команды несколько раз за одну сессию, и они будут обрабатываются и компилироваться всего один раз. Это может дать небольшой прирост производительности.

Поскольку Вы спросили, как можно реализовать защиту от инъекций на примере вставки, вот Вам пример:

$preparedStatement = $db->prepare(''INSERT INTO table (column) VALUES (:column)'');
$preparedStatement->execute(array('':column'' => $unsafeValue));

Способ 2. Экранирование строк

Есть и другой, более «короткий» способ защититься от SQL-инъекций. Он сводится к экранированию всех динамических данных, которые будут использоваться в запросе. Экранирование заменяет кавычки на символы «\»», апостроф на «\»», а обратную косую черту на «\\». Это позволяет предотвратить внедрение вредоносного фрагмента в то место, где ожидаются данные. Делается это с помощью функции mysql_real_escape_string(). Ваш пример будет иметь вид:

// соединение
$unsafe_variable = $_POST["user-input"];
$safe_variable = mysql_real_escape_string($unsafe_variable);
mysql_query("INSERT INTO table (column) VALUES (''" . $safe_variable . "'')");
// разъединение

З.Ы. Касательно перевода терминологии не уверен.

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector