Используйте так называемые готовые выражения (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));
Есть и другой, более «короткий» способ защититься от 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 . "'')"); // разъединение
З.Ы. Касательно перевода терминологии не уверен.