Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Безопасная эксплуатация Apache, часть 10: модуль mod_security (продолжение)

Оригинал: Securing Apache, Part 10: mod_security
Автор: Arpit Bajpai
Перевод: А.Панин

Начало статьи: "Безопасная эксплуатация Apache, часть 10: модуль mod_security"

Правила для защиты от наиболее распространенных атак

Давайте рассмотрим некоторые правила для отражения наиболее распространенных атак на веб-приложения.

SQL-инъекции

Предположим, что производится работа с приложением, уязвимым для атак на основе SQL-инъекций. Взломщик может попытаться удалить все записи из таблицы MySQL с помощью следующего запроса:
http://www.example.com/login.php?user=arpit';DELETE%20FROM%20users--
Атака может быть предотвращена с помощью следующей директивы:
SecFilter "delete[[:space:]]+from"
Как только соответствующий запрос захватывается фильтром, в журнале событий audit_log делается аналогичная запись:
В ответ на вредоносный запрос выполняется действие, заданное директивой SecFilterDefaultAction (запрос отклоняется, создается запись в журнале событий и взломщик получает сообщение об ошибке со статусом 500). Если вы хотите выполнить другое действие (например, выполнить переадресацию на HTML-страницу с нестандартным предупреждением), вы можете сформировать правило следующим образом:
SecFilter "delete[[:space:]]+from" log,redirect:http://example.com/invalid_request.html
Для предотвращения атак на основе SQL-инъекций, мы можем использовать некоторые другие директивы, такие, как:
SecFilter "insert[[:space:]]+into"
SecFilter "select.+from"
SecFilter "drop[[:space:]]table"
SecFilter create[[::space:]]+table
SecFilter update.+set.+=
SecFilter union.+select
SecFilter or.+1[[:space:]]*= [[:space:]]1
SecFilter '.+--
SecFilter xp_enumdsn
SecFilter xp_cmdshell
SecFilter xp_regread
SecFilter xp_regwrite
SecFilter xp_regdeletekey

Последние пять директив используются специально для предотвращения атак на основе SQL-инъекций, специфичных для серверов MS SQL.

Единственной проблемой директивы SecFilter является то обстоятельство, что с помощью нее исследуется весь запрос, а не его определенные поля. В данном случае является полезной директива SecFilterSelective; она позволяет задать те области, которые должны исследоваться. Ее синтаксис:
SecFilterSelective ОБЛАСТЬ КЛЮЧЕВОЕ_СЛОВО [ДЕЙСТВИЯ]
В данном случае параметр ОБЛАСТЬ определяет то, какая область запроса будет исследована. Следовательно, для противодействия атакам на основе SQL-инъекций, вы также можете использовать:
SecFilterSelective SCRIPT_FILENAME "login.php" chain
SecFilterSelective ARG_user "!^[a-zA-Z0-9\.@!]{1,10}$"

Код выше проверяет параметр user на то, состоит ли его значение только из заданных разрешенных символов. Если по какой-либо причине вам не подходит это решение и необходимо использовать список запрещенных символов, по крайней мере следует убрать символы одиночных кавычек ('), точек с запятыми (;), дефисов (-) и скобок (()).

XSS-атаки

Для борьбы с XSS-атаками мы можем использовать следующие директивы:
SecFilter "<(.|\n)+>"
SecFilter "<[[:space:]]*script"
SecFilter "<script"
SecFilter "<.+>"
А также некоторые дополнительные фильтры, подобные следующим:
SecFilterSelective THE_REQUEST "<[^>]*meta*\"?[^>]*>"
SecFilterSelective THE_REQUEST "<[^>]*style*\"?[^>]*>"
SecFilterSelective THE_REQUEST "<[^>]*script*\"?[^>]*>"
SecFilterSelective THE_REQUEST "<[^>]*iframe*\"?[^>]*>"
SecFilterSelective THE_REQUEST "<[^>]*object*\"?[^>]*>"
SecFilterSelective THE_REQUEST "<[^>]*img*\"?[^>]*>"
SecFilterSelective THE_REQUEST "<[^>]*applet*\"?[^>]*>"
SecFilterSelective THE_REQUEST "<[^>]*form*\"?[^>]*>"

Хотя эти фильтры и позволяют обнаружить большое количество XSS-атак, они не позволяют полностью защитить приложение. Из-за огромного количества различных языков сценариев для взломщика становится возможным создание множества методов реализации XSS-атак, с помощью которых данные фильтры могут быть преодолены. Следовательно, можно только посоветовать вам постоянно работать над добавлением своих собственных фильтров.

Для защиты кук, хранящих идентификаторы сессий PHP, от XSS-атак могут использоваться следующие фильтры:
SecFilterSelective ARG_PHPSESSID "!^[0-9a-z]*$"
SecFilterSelective COOKIE_PHPSESSID "!^[0-9a-z]*$"

Атаки исполнения системных команд

Для защиты от атак исполнения системных команд вы можете использовать следующие директивы:
SecFilter /etc/password
SecFilter /bin/ls
В данном случае взломщик может попытаться использовать строку, аналогичную /bin/./sh для обхода фильтра, но модуль mod_security автоматически приводит путь /./ к виду / и // к виду /, а также декодирует символы, к которым было применено URL-кодирование. Вы также можете использовать список разрешенных символов:
SecFilterSelective SCRIPT_FILENAME "directory.php" chain
SecFilterSelective ARG_dir "!^[a-zA-Z/_-\.0-9]+$"
Данный набор связанных правил позволяет использовать только буквы, числа, символ подчеркивания, дефис, прямой слэш и точку в параметре dir. Фильтрация имен директорий, содержащих исполняемые файлы, является также хорошим вариантом и может выполняться следующим образом:
SecFilterSelective THE_REQUEST "/^(etc|bin|sbin|tmp|var|opt|dev|kernel)$/"
SecFilterSelective ARGS "bin/"

Атаки фиксации сессий

В ходе процесса фиксации сессий, в одной из его фаз, взломщику необходимо каким-либо образом передать желаемый идентификатор сессии браузеру жертвы атаки. Мы можем нейтрализовать угрозу, применив следующие директивы:
# Слабая защита от XSS-атак, позволяющая использование стандартных HTML-тэгов
SecFilter "<[[:space:]]*script"
# Защита от XSS-атак (HTML/Javascript-инъекций)
SecFilter "<.+>"
# Блокировка передачи кук и идентификаторов сессий в строках URL
SecFilterSelective THE_REQUEST "(document\.cookie|Set-Cookie|SessionID=)"

Атаки обхода директорий

Для противодействия атакам обхода путей или директорий чаще всего применяются следующие директивы:
SecFilter "\.\./"
SecFilterSelective SCRIPT_FILENAME "/scripts/foo.cgi" chain
SecFilterSelective ARG_home "!^[a-zA-Z].{15,}\.txt"

Два последних фильтра связаны и должны отклонять все параметры аргумента home, являющиеся именами файлов, длина которых превышает 15 символов и которые не имеют расширения .txt.

Аналогично вы можете предотвратить атаки, основанные на предположениях о расположении ресурсов, и защитить важные файлы от несанкционированного использования. Для начала следует удалить все файлы, не предназначенные для публичного доступа из всех директорий, доступ к содержимому которых может осуществляться с помощью веб-сервера. После этого вы можете создать фильтры для установления чьих-либо попыток доступа к данным файлам:
SecFilterSelective REQUEST_URI "^/(scripts|cgi-local|htbin|cgibin|cgis|win-cgi|cgi-win|bin)/"
SecFilterSelective REQUEST_URI ".*\.(bak|old|orig|backup|c)$"

Эти фильтры запрещают доступ к неиспользуемым, но часто исследуемым директориям и временным файлам с соответствующими расширениями.

Динамически создаваемые с помощью функции индексации директорий веб-страницы должны иметь заголовок, начинающийся со строки "Index of /". Мы можем использовать это обстоятельство как сигнатуру и добавить следующие директивы для обнаружения и запрета доступа к данной информации:
SecFilterScanOutput On
SecFilterSelective OUTPUT "\<title\>Index of /"

Раскрытие важной информации

В последнем примере мы использовали возможность фильтрации выходных данных с помощью модуля mod_security и параметра OUTPUT, для активации которой следует добавить директиву SecFilterScanOutput On в файл настроек. Мы можем простейшим образом установить фильтр для отслеживания стандартных сообщений об ошибках базы данных, отправляемых клиенту, и генерации стандартного сообщения со статусом 500 вместо подробного сообщения:
SecFilterScanOutput On
SecFilterSelective OUTPUT "An Error Has Occurred" status:500
SecFilterSelective OUTPUT "Fatal error:"
Фильтрация выходных данных может быть использована для обнаружения успешных проникновений. Эти правила будут исследовать выходные данные с целью поиска стандартных ключевых слов, указывающих на факт исполнения команд на сервере.
SecFilterSelective OUTPUT "Volume Serial Number"
SecFilterSelective OUTPUT "Command completed"
SecFilterSelective OUTPUT "Bad command or filename"
SecFilterSelective OUTPUT "file(s) copied"
SecFilterSelective OUTPUT "Index of /cgi-bin/"
SecFilterSelective OUTPUT ".*uid\=\("

Безопасная загрузка файлов

Модуль mod_security способен вмешиваться в процесс загрузки файлов с использованием запросов POST и запросов PUT с кодированием multi-part/form-data. Загрузка всегда производится в директорию для временных файлов. Вы можете выбрать эту директорию, использовав директиву SecUploadDir:
SecUploadDir /tmp
Лучшим выбором будет отдельная директория для хранения файлов, доступ к содержимому которой разрешен только для учетной записи пользователя, которую использует веб-сервер. В противном случае другие пользователи сервера смогут получить доступ к файлам, загруженным с помощью веб-сервера. Вы можете выбрать внешний сценарий для проверки файла перед тем, как он будет передан для обработки веб-приложению. Директива SecUploadApproveScript позволяет сделать это таким же образом, как в примере ниже:
SecUploadApproveScript /usr/local/apache/bin/upload_verify.pl

Атаки удаленного включения файлов

В общем случае атаки удаленного включения файлов достаточно просто идентифицировать с помощью директивы, подобной следующей:

Другие способы повышения безопасности

Вы можете заблокировать IP-адреса с помощью следующей команды:
SecFilterSelective "REMOTE_ADDR" "^192.168.1.1$"
Если в вашей форме комментариев есть поле для ввода строки URL и вы хотите исследовать введенную строку на наличие подстроки c99, вы можете сделать это следующим образом:
SecFilterSelective "ARG_url" "c99"
Следующая директива помогает серверу в борьбе с исследованием реализации протокола HTTP и позволяет принимать только запросы с корректными версиями протокола:
SecFilterSelective SERVER_PROTOCOL !^HTTP/(0\.9|1\.0|1\.1)$
Обычно на фазе подготовки к атаке взломщики ведут поиск названия и версии веб-сервера. Веб-серверы обычно отправляют свое название вместе с каждым ответом HTTP в параметре заголовка Server. Сервер Apache особенно удобен в данном плане; по умолчанию он отправляет не только название и полную версию, а также позволяет модулям добавить свои имена и версии в строку для отправки. Вы можете ввести взломщиков в заблуждение, использовав аналогичную директиву:
SecServerSignature "Microsoft-IIS/5.0"
Инъекция кода PHP не может быть осуществлена напрямую, но есть возможность сохранения кода на диск для его последующего исполнения в ходе атаки локального включения файлов. Следующее правило обнаружит попытку осуществления такой инъекции, но проигнорирует документы XML, использующие подобный синтаксис:
SecRule ARGS "@rx <\?(?!xml)"

Журналирование событий

Существуют три места, в которых, в зависимости от настроек, вы можете обнаружить журналы событий модуля mod_security:
  • Журнал отладки модуля mod_security: Если запись отладочных сообщений включена с помощью директив SecFilterDebugLevel и SecFilterDebugLog, он содержит большое количество записей для каждого обработанного запроса. Каждая запись ассоциируется с уровнем важности в диапазоне от 0 (вообще без сообщений) до 4 (максимально подробные сообщения). В обычных условиях следует устанавливать уровень важности для сообщений отладки равным нулю и повышать его только в случаях отладки вашего набора правил.
  • Журнал ошибок Apache: Некоторые сообщения из журнала отладки добавляются в журнал ошибок Apache (даже если вы установите уровень важности для сообщений отладки модуля mod_security равным 0). Обычно это сообщения, требующие внимания со стороны администратора, такие, как информация об отклоненных запросах.
  • Журнал аудита модуля mod_security: Когда запись сообщений аудита включена (с помощью директив SecAuditEngine и SecAuditLog), модуль mod_security может записывать каждый запрос (и его тело в случае включения буферизации данных запросов) и соответствующий ему заголовок ответа.
Ниже представлен пример сообщения об ошибке, сгенерированного при обнаружении некорректных данных в куках:
[Tue Jun 26 17:44:36 2011] [error] [client 127.0.0.1]
mod_security: Access denied with code 500. Pattern match "!(^$|^[a-zA-Z0-9]+$)"
at COOKIES_VALUES(sessionid) [hostname "127.0.0.1"]
[uri "/test.php"] [unique_id 3434fvnij54jktynv45fC8QQQQAB]

Сообщение указывает на то, что запрос был отклонен ("Access denied") со статусом 500 по той причине, что данные идентификатора сессии в куках не соответствуют шаблону !(^$|^[a-zA-Z0-9]+$). (Шаблон позволяет использовать пустые куки, но в случае наличия в них идентификатора, он должен состоять из одной или более букв и цифр.)

Примечание: Снова хотел бы обратить внимание на то, что ни журнал LFY, ни я не несем ответственности за недобросовестное использование приведенной в статье информации. Все описания техник атак приведены для того, чтобы дать вам необходимые знания для защиты вашей инфраструктуры. Пожалуйста, используйте описанные инструменты и техники добросовестно.

В данной статье описываются только основы работы с модулем mod_security. Для получения более подробной информации о разработке правил и других важных директивах обратитесь к книге Ivan Ristic ModSecurity Handbook, которую должен прочитать каждый интересующийся данной темой.

Мы рассмотрим другие пути защиты Apache в следующей статье. Всегда помните: нужно знать все о взломе, не не заниматься им.

Следующая статья серии: "Безопасная эксплуатация Apache, часть 11: использование журналов событий и других средств"