Содержание статьи
Все чаще в Cети можно встретить сайты, которые скрывают параметры, передаваемые приложению посредством модуля Apache – mod_rewrite. Часто у веб-разработчиков создается иллюзия, что таким образом можно защитить веб-приложение от атак с использованием уязвимостей SQL Injection, Cross-Site Scripting и т.п. На самом деле это является распространенным заблуждением, аналогичным тому, что сокрытие fingerprint-сервисов увеличивает их безопасность. Безусловно, использование mod_rewrite для сокрытия передаваемых параметров к приложению, равно как и сокрытие отпечатков, является некоторой преградой для атакующего. Но, как говорится, «нет такой преграды, которую нельзя было бы обойти»!
Введение
Mod_rewrite – достаточно мощный инструмент для URL-преобразований «на лету». Этот замечательный модуль веб-сервера Apache предоставляет поистине безграничные возможности. На данный момент модуль чаще всего применяется для:
- поисковой оптимизации (SEO);
- защиты от прямых загрузок, так как скрывается реальное местоположение файла;
- сокрытия иерархии поступающих параметров, каталогов и сценариев веб-приложения путем их централизованного динамического преобразования;
- разграничения доступа: mod_rewrite может проверять значения HTTP-заголовков, в том числе значение COOKIE на соответствие правилам и по результатам проверок проводить (или не проводить) перенаправление.
Чаще всего корректно настроенный mod_rewrite затрудняет возможности поиска и эксплуатации уязвимостей веб-приложения. Это происходит по следующим причинам:
1. Трудно распознать реальное предназначение элемента URL. Например, если мы видим ссылку вида http://www.example.com/main/search/stroka_poiska
, невозможно понять, какой из элементов URL является относительным путем от корневого каталога веб-сервера; что является названием сценария, а что является параметром этого сценария. Это сильно затрудняет анализ структуры веб-приложения. Например, следующие правила позволят одной и той же ссылке соответствовать различным реальным представлениям структуры веб-приложения:
RewriteRule ^search/(.+)$ search.php?search=$1
При таком правиле ссылка http://www.example.com/main/search/stroka_poiska
соответствует сценарию search.php, который располагается в папке /main/ относительно корневого каталога веб-сервера, вызванному с параметром search=stroka_poiska
RewriteRule ^(.+)/(.+)$ script.php?act=$1&value=$2
По данному правилу та же самая ссылка соответствует сценарию script.php, который находится в папке main и вызван с параметрами act=search&value=stroka_poiska
RewriteRule ^(.+)/(.+)/(.+)$ $1.php?value1=$2&value2=$3
А по этому правилу такая же ссылка соответствует сценарию main.php, который находится в корневом каталоге веб-сервера и вызван с параметрами value1=search&value2=stroka_poiska
Кроме того, благодаря гибкости используемых mod_rewrite регулярных выражений, даже схожие по виду URL-адреса могут обращаться к абсолютно разным сценариям.
Например, данные правила:
RewriteRule ^(.+)/(.+)$ script1.php?value1=$2&value2=$3
RewriteRule ^(.+)/(.+)/(.+)$ script2.php?value1=$2&value2=$3
отправят 2 схожих запроса разным сценариям:
http://www.example.com/stroka1/stroka2
http://www.example.com/stroka1/stroka2/stroka3
2. Трудно определить язык программирования, на котором написано приложение. За ссылкой http://www.example.com/main/articles/statya.html
может находиться как серверный сценарий на языке PHP, ASP или Perl, так и статическая страница на языке HTML;
3. Наличие регулярных выражений, которые можно использовать в правилах перезаписи mod_rewrite, позволяет фильтровать входные параметры (далее будет рассмотрен пример);
4. При автоматизации поиска уязвимостей необходимо заменять некоторые символы (например, слеш ("/") на %2F (hexadecimal encoding) или %252F (double encoding)), так как они обрабатываются еще на стадии «разбора» URL-адреса в mod_rewrite.
В связи с этим многие разработчики и администраторы предпочитают «маскировать» наличие уязвимостей с помощью mod_rewrite, а не обнаруживать и исправлять проблемы. Но такой подход, как и любой метод, основанный на подходе Security Through Obscurity, работает весьма плохо.
Методика работы
Основная идея поиска уязвимостей при включенном mod_rewrite – это перебор (brute-force), позволяющий определить реальные имена реальных параметров серверных сценариев, в которые подставляются значения из правил перезаписи (rewrite rules) mod_rewrite. Основные особенности перебора:
- использование в одном запросе множества параметров (количество параметров ограничивается максимальной длиной URL (по умолчанию для веб-сервера Apache 2.x – 8192 символа, для IIS – 16 384 символа);
- применение метода бинарного поиска (дихотомии) для обнаружения необходимых параметров;
- словарный перебор (использование популярных названий параметров и префиксов) – id, count, и т.д. в сочетании с полным перебором названий параметров (комбинированные атаки);
- различные варианты анализа результатов (рассматривается далее);
- возможность рекурсивного поиска параметров (для поиска всего множества параметров одного сценария).
Рассмотрим алгоритм поиска уязвимостей в веб-приложении при включенном mod_rewrite.
1. Определение реального имени серверного сценария.
Используются стандартные и популярные названия сценариев, такие как index.php, main.php. Необходимо определить, существует ли данный сценарий (например, по наличию ошибки «404 – Not Found»). Иногда правила могут перезаписывать любые URL-адреса, начиная с корневого каталога веб-сервера, то есть запрос http://www.example.com/index.php
уже будет вести на абсолютно другой сценарий (RewriteRule ^(.+)$ script.php?$1)
. В таком случае дальнейшие проверки не имеют смысла.
2. Определение параметров, поступающих в приложение.
Наиболее часто разработчики веб-приложений используют такие популярные названия параметров, как id, file и т.д. Учитывая это, необходимо проверить:
- самые популярные названия переменных (id, path, page, debug, cat и проч.);
- короткие названия переменных (1-5 символов) в алфавите [a-z0-9-_] – полный перебор;
- «гибридные» названия – по формулам:
- "префикс" + "популярное название параметра";
- "популярное название параметра" + "постфикс";
- "полный перебор" + "разделитель (_,-)" + "популярное название параметра";
- "популярное название параметра" + "разделитель (_,-)" + "полный перебор".
- для кода, в названиях переменных которого используются различные суффиксы и префиксы,
переменные-массивы (param[]).
Говоря о последнем типе параметров, нужно отдельно уточнить: дело в том, что если в PHP-сценарии к параметру, инициализированному как массив (http://example.com/index.php?param[]=value
), произойдет обращение как к простому типу, будет выведена ошибка (в зависимости от error_reporting level), что приведет к раскрытию установочного пути.
Также можно использовать:
- массивы GLOBALS (
http://example.com/index.php?GLOBALS[var]=value
); - стандартные переменные _SERVER (в определенных случаях можно перезаписать и их);
- переменные в сочетании с их zend_hash_key (для обхода уязвимых функций unset()).
3. Определение значения параметров.
Для решения этой задачи важно использовать различные варианты параметров. Если, например, везде подставлять в значение 1, то велика вероятность, что оно совпадет со значением переменной по умолчанию, и сервер вернет тот же ответ. Также различные параметры – это различные ошибки. А если проводить поиск по значению параметра в ответе (потенциальные XSS, Local File Including, Path Traversal, etc), то для каждого параметра потребуется генерировать уникальное значение.
Возможные варианты, их предназначение, плюсы и минусы:
- Числовое значение: 0,1,2,.. Самый простой вариант. Можно обойтись 3 вариантами: 0, 1 и >1. Из плюсов – минимальная длина строки запроса, что практически не сказывается на производительности работы.
- Ошибочное значение: "‘", "../", "a%00" и т.д. – различные наборы символов, которые могут привести к потенциальным ошибкам, по сигнатурам которых можно определить присутствие параметра.
- Фиксированное значение параметра. Например, если существует URL
http://example.com/main/search/stroka_poiska
, то, зафиксировав ответ сценария на значение stroka_poiska и подставив это значение во все параметры, по ответу, совпадающему с эталонным значением, можно будет найти параметр, отвечающий за конкретную позицию в URL-адресе, см. пример ниже. - Случайное число. Генерируя достаточно длинные случайные числа (5-9 символов), можно искать совпадение с этими числами в ответах сценариев. Случайные числа дают большую вероятность отсутствия ошибки второго рода (False Positive).
Например, URL http://example.com/main/search/test
отвечает за сценарий поиска с параметром "test". Нам необходимо найти оригинальный параметр строки поиска. Для этого мы фиксируем сигнатуру со страницы http://example.com/main/search/test (например, «по запросу <b>test</b>
найдено») и проводим перебор по всем параметрам, подставляя в значение параметра "test". Анализируя ответы, по наличию сигнатуры можно найти необходимый параметр.
4. Составление запроса и подбор.
Составить запрос вида http://example.com/script.php?param1=value¶m2=value&…&abc=value
. Ограничение на длину URL запроса составляет 8192 символа (для сервера Apache). Это означает, что все параметры из алфавита [a-z0-9] с длиной до 4 символов можно перебрать примерно за 5880 запросов. При хорошей скорости интернета это займет 3-5 минут.
5. Анализ ответов и определение наличия параметра.
Эта часть работы алгоритма – самая важная, поскольку именно она определяет эффективность работы. Отличия в структуре веб-приложений и различные условия обуславливают решение о выборе того или иного метода анализа ответа. Рассмотрим плюсы и минусы различных походов:
определение по длине ответа
плюсы:
- Самый быстрый и простой способ. Необходимо лишь узнать длину эталонного запроса (без параметров) и сравнивать ее с длиной запросов с параметрами.
минусы:
- Данный метод неприменим в ситуациях, когда каждый раз сценарий генерирует ответ с уникальным содержимым (баннеры, случайный контент, наличие строки запроса в ответе).
определение по сигнатурам случайных значений переменных
плюсы:
- Уменьшение числа ложных срабатываний.
минусы:
- Необходимо удалять ложные срабатывания, связанные со штатным попаданием случайного значения в ответ (например, при штатном наличии данных запроса в ответе).
- Уменьшение скорости из-за увеличения длины значений параметров (с 1-2 символов до 5-7 символов, что увеличивает время перебора в 1,5-2 раза для параметров длиной до 4 символов).
определение по фиксированным ответам
плюсы:
- Точность поиска.
минусы:
- Сфокусированность поиска – поиск происходит только по одному конкретному параметру.
* например, когда необходимо определить параметры на страницеhttp://example.com/main/search/stroka_poiska
, мы должны подставлять во все переменные значение "stroka_poiska" и отслеживать ответ. Верным будет параметр, попавший в запрос, ответ на который совпал по содержимому с первоначальной страницей.
определение по сигнатурам ошибок
плюсы:
- Почти полное отсутствие ошибок второго рода (False Positive – ложное срабатывание), что исключает идентификацию наличия параметра в запросе, когда на самом деле его в нем нет.
минусы:
- Требуется использовать базу сигнатур ошибок. Если наличие параметра не вызывает ошибку, то данный метод не выявит параметр.
Как видно из вышеизложенного, различные методы эффективны в разных ситуациях. Самым простым и, порой, наиболее действенным является первый подход, но иногда нельзя выявить параметр даже с помощью сложных методов. Поэтому желательно использовать различные методики или решать в каждом конкретном случае отдельно, какая методика уменьшит число ложных срабатываний. В конце концов, если в результате работы будет выявлено 10-15 переменных, они всегда могут быть проверены на предмет ложных срабатываний вручную.
Практическая реализация
В качестве практической демонстрации эффективности приведенных методов может быть использован фазер, который ты найдешь на прилагаемом к журналу диске. Фазер реализует следующие возможности:
- Полный перебор по алфавиту, по наиболее часто встречаемым параметрам (указываются в файле params.txt), в комбинированном режиме ("популярное название параметра" + "разделитель (_,-)" + "полный перебор"). Также можно указать флаг, при котором каждая переменная будет представлена в виде массива (param[]).
- Использование дихотомии для поиска параметров.
- Поиск по длине ответа (указывается первоначальная страница, ее размер).
- Выбор первоначальной страницы с параметрами (например,
http://example.com/index.php?page=admin
) для поиска множества вложенных параметров (указанные параметры, естественно, будут исключаться из проверки). - Выбор символов, подставляемых в значения переменных.
З.Ы.: Некоторые из этих механизмов реализованы в сканере MaxPatrol компании Positive Technologies.
И напоследок...
Приведенный метод подходит не только для оценки защищенности веб-приложений, использующих mod_rewrite, но и для поиска переменных, которые могут быть перезаписаны при включенном параметре register_globals, а также для поиска недокументированных возможностей, таких как различные отладочные ("debug") режимы и т.д. Удачного тебе поиска!
Yummy...
На нашем диске ты можешь найти небольшой фазер, который умеет делать следующее:
- Полный перебор по алфавиту;
- Использовать дихотомию для поиска параметров;
- Есть возможность поиска по длине ответа;
- Проводить комбинированные атаки.
Немного ссылок по теме:
- owasp.org/index.php/Double_Encoding
- dimoning.ru/kak-napisat-svoy-dvizhok-bloga-1.html
- webscript.ru/stories/07/02/01/2099269]
- ru.wikipedia.org/wiki/Двоичный_поиск
- raz0r.name/mysli/proveryajte-tip-dannyx/
- hardened-php.net/globals-problem
- hardened-php.net/advisory_192005.78.html
- wisec.it/vulns.php?id=10
- hardened-php.net/hphp/zend_hash_del_key_or_index_vulnerability.html
WARNING
Внимание! Информация представлена исключительно с целью ознакомления! Ни авторы, ни редакция за твои действия ответственности не несет!