SQL-инъекции

База данных

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

Пусть у нас есть доска объявлений, на ней регистрируются пользователи, мы разрешаем пользователям через интерфейс удалять свои записи. Вот код PHP-скрипта:
mysql_query('DELETE FROM messages WHERE id='.$message_id.' AND user_id='.$user_id);

Пояснения: переменная message_id приходит от ссылки "Удалить" ($_REQUEST['message_id']), в ней содержится идентификатор удаляемой записи (целое число); переменная user_id хранится в сессии, мы записываем в нее идентификатор пользователя при его успешной авторизации на сайте.

Теперь предположим, что хакер подделал адрес ссылки для удаления и вместо «?message_id=15» отправил нам «?message_id=15 OR 1=1». После подстановки этого значения в запрос он станет таким:
DELETE FROM messages WHERE id=15 OR 1=1 AND user_id=3

Мы видим, что данные стали выражением, в выражение попало логическое "или" (OR), в результате чего хакер "выключает" проверку user_id и может удалять чужие записи. В качестве разминки могу предложить придумать такой запрос, которым хакер удалит с нашей доски объявлений все записи разом.

Другой пример: проверка логина и пароля пользователя, которые поступают в переменных $login и $password:
mysql_query('SELECT id FROM users WHERE login="'.$login.'" AND password="'.$password.'"');

Если в $login хакер отправляет «admin" OR 1="1», то его пустят на сайт под логином admin даже без знания пароля:
SELECT id FROM users WHERE login="admin" OR 1="1" AND password=""

А если напишет «" OR 1=1 OR 1="1», то его вообще пустят под первым попавшимся в базе данных пользователем.

Таким образом, основным правилом противодействия SQL-инъекциям является недопущение ситуации, когда данные интерпретируются как выражения. Нужно либо насильно приводить значения в ожидаемый тип (функции intval, floatval, если ожидается число), либо просто заключать их всех в кавычки и экранировать содержащиеся внутри них спецсимволы.

В языке PHP есть специальная функция, экранирующая текст перед вставкой в MySQL-запрос, она называется mysql_real_escape_string. Используемые иногда вместо нее mysql_escape_string, addslashes и (да, да, встречаются и такие странные люди) htmlspecialchars либо неэффективны (см. мануал на www.php.net), либо предназначены для другого (как последняя).

Изначально в язык PHP были введены так называемые «Волшебные кавычки» (Magic Quotes). Это функциональность, при которой PHP сам добавляет обратную косую черту перед всеми кавычками (и уже имеющимися обратными косыми чертами) в данных, поступающих скрипту извне. С одной стороны, это некоторым образом защищает скрипт, автор которого не заморачивал себе голову насчет безопасности своего творения. С другой стороны, данные "портятся" все подряд, даже те, которые и не предначены для запросов к базе. Не хочется же видеть на сайте приветствие "Здравствуйте, д'Артаньян"? И приходится либо чистить данные функцией stripslashes, либо вообще отключать magic_quotes в настройках сервера.

Да и защита через magic_quotes не стопроцентна: она не предотвратит первую из приведенных выше инъекций, с конструкцией «WHERE id='.$message_id» — кавычек вокруг аргумента и так нет, хакеру не нужно вставлять закрывающие кавычки. Также не учитывается кодировка соединения с базой данных.

В конце концов, сами авторы PHP не советуют использовать «Magic Quotes» и прекращают их поддержку начиная с 6-ой версии PHP.

Таким образом, уповать на то, что скрипт работает в условиях действующих magic_quotes, не следует, но следует обрабатывать данные перед вставкой в SQL-запросы функциями mysql_real_escape_string / pg_escape_string и обязательно заключать значения в SQL-запросе в кавычки. При этом крайне желательно подвергать такой обработке все данные, участвующие в SQL-запросах, насколько бы надежным ни казался их источник.

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


Источник: http://www.captcha.ru

Рекомендуем



Register Globals Если программист не следит за начальной инициализацией переменных, может возникнуть уязвимость, иллюстрируемая простым примером:


XSS Зачастую, все-таки надо предоставить пользователю возможность как-то оформлять свои сообщения: выделять цитаты, менять шрифты, раскрашивать тексты разным цветом, вставлять картинки и таблички, как, к примеру, сделано на LiveJournal


Загрузка файлов Таким образом, контролировать для обеспечения безопасности следует именно расширение файла, а проверки через определение mime-type и через попытку открыть файл функцией getimagesize имеют смысл только для контроля того, что вместо картинки не будет загружен мусор, безвредный, но картинкой не являющийся