Защита от SQL-инъекций
15:05, 05.12.2022
В этой статье расскажем, как работает SQL-инъекция, чем опасны подобные атаки, а также рассмотрим механизмы и способы защиты. Заранее отметим, что при правильном подходе вы легко сможете купировать даже малейшую вероятность того, что злоумышленники достигнут успеха. Если же ничего не предпринимать – SQL-инъекции могут нанести серьезный ущерб вашему веб-серверу.
Что собой представляет и как работает SQL инъекция
SQL injection – распространенный способ взлома сайтов и программного обеспечения, которые работают под управлением баз данных (БД). Суть метода сводится к внедрению произвольного SQL кода, что в итоге позволит хакеру различными способами взаимодействовать с данными СУБД:
- читать содержимое;
- удалять данные;
- добавлять новые данные.
Кроме того, в отдельных случаях злоумышленник может получить доступ к чтению и записи локальных файлов на сервере, выполнять произвольные команды и т.д.
Происходит это следующим образом. На большинстве сайтов есть базы данных, где хранится вся информация. Когда посетитель сайта пытается загрузить страницу, базе данных отправляется запрос. И всё бы ничего, но пользователь может модифицировать запрос – в процессе создания комментария, во время поиска или даже просто при переходе с одной страницы на другую. Эти запросы – окно возможностей для SQL инъекции. Запуск действия, которое не было предусмотрено создателем скрипта. Рассмотрим пример.
Супруга оставляет мужу записку, чтобы он дал немного наличных денег Николаю, оставив их на кухонном столе. Потенциальный SQL запрос мог бы выглядеть так:
ДОСТАНЬ ИЗ кошелька 200 ГРИВЕН И ОСТАВЬ ИХ НА СТОЛЕ ДЛЯ Николая
Сделав это, женщина оставила записку на столе и ушла на работу. Проснулась Маша, сестра Николая, увидела записку и добавила в неё похожим почерком пару слов:
ДОСТАНЬ ИЗ кошелька 200 ГРИВЕН И ОСТАВЬ ИХ НА СТОЛЕ ДЛЯ Николая ИЛИ Маши
Когда проснулся муж, он без всяких задних мыслей решил, что оба ребенка в курсе, для чего нужны эти деньги. Увидев Машу, он ей сообщил, что деньги на столе – пусть, мол, берет.
Маша добилась своего нечестным путем, но в итоге она с деньгами, а Николай остался ни с чем. Это и есть простой пример SQL-инъекции, только простыми словами.
Теперь рассмотрим более приближенный к реальности пример. Вот так выглядит стандартный запрос ID при поиске:
SELECT id,title,content FROM posts WHERE title LIKE '%запрос_пользователя%'
Но теперь давайте представим, что вместо стандартных ключевых слов пользователь введет следующую комбинацию:
1%'; DROP TABLE posts LIKE '%;
Результатом станет рабочий запрос, которого разработчик базы данных не смог предусмотреть:
SELECT id,title,content FROM posts WHERE title LIKE '%1%'; DROP TABLE posts LIKE '%%'
Подобная схема может сработать с любым запросом, где предусмотрен ввод данных пользователей – при условии, что разработчики или специалисты в области безопасности не предусмотрели необходимые механизмы защиты. В данном случае для решения проблемы достаточно просто экранировать все кавычки в пользовательских запросах. Далее мы рассмотрим основные способы защиты от SQL-инъекций.
Защита сайта от SQL инъекции на уровне программного кода
При использовании языка программирования PHP можно экранировать кавычки с помощью таких функций:
- mysql_real_escape_string;
- mysqli_real_escape_string.
При условии, что каждая переменная, используемая в запросах к БД, будет профильтрована, проблем точно не возникнет. Важно лишь, чтобы фильтрацию провели на уровне CMS или программного кода.
Проблема в том, что создание небезопасных запросов к базе данных занимает намного меньше времени, чем создание безопасных, с экранированием. И из-за этого многие сайты оказываются уязвимы.
Настройка защиты для веб-сервера
Если доработать код возможности нет, можно отфильтровать все значения переменной REQUEST в начале скрипта. Для этого используйте такой код:
if (!function_exists("clean")) { if (get_magic_quotes_gpc()) { function magicquotes_Stripslashes(&$value, $key) { $value = stripslashes($value); } $gpc = array(&$_COOKIE, &$_REQUEST); array_walk_recursive($gpc, 'magicquotes_Stripslashes'); } function clean(&$value, $key) { //эта функция экранирует все кавычки. $value = mysql_real_escape_string($value); } } $req = array(&$_REQUEST); array_walk_recursive($req, 'clean');
При использовании PHP 7 следует применять функцию mysqli_real_escape_string, так как расширение mysql начиная с этой версии удалено. Экранирование кавычек осуществляется функцией clean и всем кодом, который ниже.
Далее для защиты веб-сервера следует добавить несколько правил в секцию сервера. Вот пример для пользователей Nginx:
set $block_sql_injections 0; if ($query_string ~ "union.*select.*\(") { set $block_sql_injections 1; } if ($query_string ~ "union.*all.*select.*") { set $block_sql_injections 1; } if ($query_string ~ "concat.*\(") { set $block_sql_injections 1; } if ($block_sql_injections = 1) { return 403; }
Таким нехитрым образом осуществляется фильтрация всех запросов, содержащих слова select и concat с кавычками. Это – верный симптом, указывающий на попытку внедрения SQL-инъекции, и все подобные запросы должны блокироваться.
Еще можно блокировать подозрительные адреса на уровне веб-сервера Apache. Проблема в том, что блокировка некоторых часто используемых ключевых слов SQL может спровоцировать также блокировку запросов обычных пользователей, так что здесь нужно соблюдать осторожность. Если уверены, что это необходимо, тогда в секцию VitualHost следует добавить несколько строк:
RewriteCond %{QUERY_STRING} [^a-z](declare¦char¦set¦cast¦convert¦delete¦drop¦exec¦insert¦meta¦script¦select¦truncate¦update)[^a-z] [NC] RewriteRule (.*) - [F]
И, в конце концов, активируйте модуль mod_security:
sudo a2enmod mod_security
Используйте все перечисленные методы в комплексе, чтобы добиться наивысшей эффективности в плане защиты от инъекций SQL.
Деление базы данных
Еще один хороший способ повысить уровень безопасности базы данных – разделить её на 2-4 части с применением принципа минимальных привилегий. Суть в том, что пользователи и отдельные программы будут иметь доступ только к той информации, которая им нужна, не больше и не меньше.
В результате разделения базы данных она реорганизуется в два файла: серверную БД, в которой содержатся таблицы с данными, и клиентскую БД, где хранятся все остальные объекты – запросы, формы, отчеты, данные кредитных карт и т.д. Помимо того, что это повышает степень защищенности от SQL инъекций, разделение базы данных также положительно сказывается на производительности веб-сервера, так как по сети отправляются только данные.
Использование расширенных систем защиты
Еще один надежный вариант – использовать аппаратные решения, работающие поверх iptables или ipfw. Существуют различные системы обнаружения вторжений на серверах HIDS, сюда относится и популярная OSSEC. Да, это решение сложнее в плане реализации, зато эффективность блокировок такого рода атак близится к 100%.
Подведение итогов
Напоследок отметим, что лучше всего использовать несколько методов в комплексе. И даже в этом случае стопроцентную защиту от SQL инъекций вам никто гарантировать не сможет – уязвимости могут быть всегда. С каждой новой версией PHP разработчики языка совершенствуют его, устраняя различные уязвимости, так что не забывайте и о регулярных обновлениях программного обеспечения. На этом мы заканчиваем наш материал и благодарим вас за внимание. Всего доброго!