Все чаще в 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 переменных, они всегда могут быть проверены на предмет ложных срабатываний вручную.

 

Практическая реализация

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

  1. Полный перебор по алфавиту, по наиболее часто встречаемым параметрам (указываются в файле params.txt), в комбинированном режиме ("популярное название параметра" + "разделитель (_,-)" + "полный перебор"). Также можно указать флаг, при котором каждая переменная будет представлена в виде массива (param[]).
  2. Использование дихотомии для поиска параметров.
  3. Поиск по длине ответа (указывается первоначальная страница, ее размер).
  4. Выбор первоначальной страницы с параметрами (например, http://example.com/index.php?page=admin) для поиска множества вложенных параметров (указанные параметры, естественно, будут исключаться из проверки).
  5. Выбор символов, подставляемых в значения переменных.

З.Ы.: Некоторые из этих механизмов реализованы в сканере MaxPatrol компании Positive Technologies.

 

И напоследок…

Приведенный метод подходит не только для оценки защищенности веб-приложений, использующих mod_rewrite, но и для поиска переменных, которые могут быть перезаписаны при включенном параметре register_globals, а также для поиска недокументированных возможностей, таких как различные отладочные ("debug") режимы и т.д. Удачного тебе поиска!

 

Yummy…

На нашем диске ты можешь найти небольшой фазер, который умеет делать следующее:

  1. Полный перебор по алфавиту;
  2. Использовать дихотомию для поиска параметров;
  3. Есть возможность поиска по длине ответа;
  4. Проводить комбинированные атаки.
 

Немного ссылок по теме:

 

WARNING

Внимание! Информация представлена исключительно с целью ознакомления! Ни авторы, ни редакция за твои действия ответственности не несет!

Оставить мнение

Check Also

Хроники битвы при Denuvo. Как «непробиваемая» игровая защита EA Origin оказалась пробиваемой

Защита от пиратства Denuvo пришла на смену SecuROM и связана с одним действующим лицом – Р…