Как стать автором
Обновить
Positive Technologies
Лидер результативной кибербезопасности

Разбор конкурса IDS Bypass на Positive Hack Days 10

Время на прочтение6 мин
Количество просмотров2.5K

Уже второй раз на конференции Positive Hack Days проходил конкурс IDS Bypass. Как и в прошлый раз (прошлый разбор), участникам предстояло не просто найти слабости в шести сервисах и утащить флаги, но и обойти IDS, которая будет им мешать. Помочь в обходе правил IDS должны были сообщения об их срабатываниях, алерты. И как известно по прошлому конкурсу, количество решений для заданий совершенно неограниченно. Поехали!

192.168.30.10 — Apache Tomcat

На порте 8080 нас встречает Apache Tomcat версии 9.0.17. Первый же поиск эксплойта под эту версию должен привести к CVE-2019-0232.

Это задание задумывалось как ознакомительное и было самым простым (как оказалось, не самым). В эксплойте видим тестовый URL с командой /cgi/test.bat?&dir. Но при таком запросе он просто виснет, а участник видит алерт IDS:

ATTACK [PTsecurity] Apache Tomcat RCE on Windows (CVE-2019-0232)

Задумывалось так, что участник будет видоизменять URL тем же образом, каким бы он делал это для обхода WAF. Регулярное выражение в правиле выглядит так: pcre: "/\.(?:bat|cmd)\?\&/U";, и вскоре бы IDS уступила участнику. Кроме того, в некоторых эксплойтах уже есть пример URL с байпасом, например такой: http://localhost:8080/cgi/test.bat%20%20?&dir. В итоге многие с легкостью выполнили задание. С конкурсом ознакомились, переходим дальше.

192.168.30.20 — PHP Bypass

Главная страница встречает нас предложением протестировать команду ls. Предупреждает, что может не сработать.

Как и ожидалось — не работает. В логе сообщение:

ATTACK [PTsecurity] file_name parameter possible command injection

Можно подумать, что в задании необходимо проэксплуатировать RCE и забрать флаг, но идея заключалась в другом. Летом 2019 года автор под псевдонимом @Menin_TheMiddle опубликовал статью о байпасе IDS и WAF. В ней шла речь о том, что ряд символов в имени GET-параметра PHP интерпретатор приводит к знаку подчеркивания («_»). Наша IDS, в отличие от PHP, этого не делает. Для примера автор использовал одно из публичных правил IDS нашей команды AttackDetection. А поскольку решающая часть правила Suricata выглядела так: pcre: "/file_name\s*=\s*[a-zA-Z\.]*[^a-zA-Z\.]/U";, то и обойти его можно было просто заменив параметр file_name на, скажем, file[name. Из-за ошибки в правиле Suricata получить флаг можно было просто послав file_name=.

192.168.30.30 — He said yes

Нас встречает форма и инструкция, как получить тот самый флаг. Достаточно просто ответить «yes» на HTTP-запрос.

Участники запускали на своих узлах веб-сервер, отвечали «yes» на входящие запросы и видели следующую строчку в логах:

JOKE [PTsecurity] Sometimes Positive Technologies hurts! No 'yes' allowed

Правило проверяло все HTTP-ответы и не пропускало те, внутри которых была строка «yes». Игровой узел также принимал только строку «yes» в нижнем регистре, и это задание набрало наибольшее число разных решений!

Задумка заключалась в том, чтобы перенаправить входящий HTTP-запрос на протокол HTTPS и уже в новом запросе ответить «yes». Для этого вектора в библиотеке requests были специально использованы параметры allow_redirects=True и verify=False. Решение выглядело так:
echo -ne "HTTP/1.1 302 Redirect\r\nLocation: https://10.8.0.2/hi_there\r\nContent-Length: 0\r\n\r\n" | sudo nc -nkvlp 80
echo -ne "HTTP/1.1 200 OK\r\nContent-Length: 3\r\nContent-Type: text/html\r\n\r\nyes" | sudo ncat -nvklp 443 –ssl

Участник @vos использовал стократное вложенное сжатие gzip для HTTP-ответа, а участник @webr0ck использовал заполнение нулями размером почти в 2 мегабайта перед строкой «yes». И в том и в другом случае Suricata оказалась бессильной.

192.168.30.40 — DCERPC

Самый дорогой таск на этом конкурсе. Участникам давались данные УЗ администратора и предлагалось проявить свои знания Windows-протоколов. Для получения флага необходимо было вытащить список всех пользователей на устройстве.

Те, кто знаком с безопасностью AD, могут сразу подумать о скрипте samrdump.py из набора impacket, но скрипт «стучится» на закрытый на узле порт 445 SMB. Строка биндинга в скрипте ncacn_np:*hostname*[\pipe\samr] фиксирована и ведет на SMB-пайп. Кроме того, из открытых портов на узле обнаруживается только 135, его слушает т. н. Endpoint Mapper. EPM отвечает за резолв RPC-интерфейсов.

Другой скрипт из набора impacket, rpcdump.py, как раз и использует EPM, чтобы узнать список текущих активных RPC-интерфейсов.

> python rpcdump.py Administrator:TastesG00d@192.168.30.40
Protocol: [MS-SAMR]: Security Account Manager (SAM) Remote Protocol
Provider: samsrv.dll
UUID    : 12345778-1234-ABCD-EF00-0123456789AC v1.0
Bindings:
          ncacn_ip_tcp:192.168.30.40[49668]
          ncacn_np:\\TASK4[\pipe\lsass]

Среди всех интерфейсов видим необходимый нам SAMR, который отвечает среди прочего и за управление пользователями. С помощью интерфейса SAM скрипт samrdump.py вытаскивает список пользователей. То есть кроме SMB-пайпа мы можем напрямую подключиться к порту 49668 и запросить список пользователей по протоколу DCERPC. Для этого необходимо пропатчить скрипт samrdump.py, чтобы он обращался вместо пайпа напрямую на интерфейс SAMR. По иному пути пошли участники @vos и @Abr1k0s. Они использовали готовый инструмент walksam из набора rpctools, единственная сложность которого заключается в использовании флага RPC_C_AUTHN_LEVEL_PKT_PRIVACY вместо RPC_C_AUTHN_LEVEL_CALL. Альтернативными способами были использование интерфейсов atsvc, svcctl, dcom и других. Все они позволяют произвольное исполнение кода и закрыты правилами IDS. Интерфейс shutdown также был закрыт. Самый необычный способ решения этого задания подразумевал удаленный поиск событий создания пользователя с помощью wevtutil:

192.168.30.50 — RDP me

Задача проста: подключиться по RDP с известной учетной записью и прочитать флаг с рабочего стола. Сложность в том, что большинство из известных RDP-клиентов заблокированы правилами IDS. Участники то и дело получали одно из следующих сообщений:

  • TOOLS [PTsecurity] xfreerdp/vinagre/remmina RDP client

  • TOOLS [PTsecurity] xfreerdp/remmina RDP client

  • TOOLS [PTsecurity] MSTSC Win10 RDP client

  • TOOLS [PTsecurity] MSTSC Win7 RDP client

  • TOOLS [PTsecurity] Rdesktop RDP client

Иногда разные RDP-клиенты ведут себя одинаково: например, многие Linux-клиенты построены вокруг одной и той же библиотеки. Таск имеет несколько решений.

Первое решение, которое было предусмотрено изначально, — это решение в лоб. Участник перебирает разные опции запуска или пробует разные клиенты и видит разные алерты IDS. После анализа своего трафика он узнает, какой именно пакет блокирует IDS. На основе этого можно сделать вывод о том, как работают правила. Правила срабатывают на определенные последовательности каналов (channelDef) в поле ClientNetworkData и на сам порядок заголовков.

Перебирая опции запуска клиента xfreerdp последних версий, можно наткнуться на опцию echo:
xfreerdp /v:192.168.30.50 /u:user /p:letmein +echo
И xfreerdp именно с такими параметрами проскочит мимо правил IDS.

Другой способ продемонстрировали @vos, @Abr1k0s и @astalavista — они подключились к серверу с использованием мобильного клиента Mocha RDP Lite. Принципиально другое решение с использованием netsed нашел участник @webr0ck. Netsed, как и обычный sed, способен подменять сетевые данные на лету. Участник просто занулил все имена каналов в ClientData пакете RDP.

192.168.30.60 — LDAP

В описании дан IP-адрес с открытым портом 389. Данных УЗ в задании нет, но сервис LDAP поддерживает анонимные подключения (bind). Однако при простом коннекте при помощи Python-библиотеки ldap3 в три строчки видим алерт IDS.

server = ldap3.Server('192.168.30.60', port=389)
connection = ldap3.Connection(server)
connection.bind()

TEST [PTsecurity] LDAP ASN1 single byte length fields prohibited

Засняли дамп своего трафика и видим, что сам bind происходит успешно, но searchRequest, который после этого послала библиотека, остается без ответа. На него и срабатывает правило IDS.

Windows-утилиты ADSIEdit и ldp, а также линуксовый ldapsearch дают похожие результаты, но с другими алертами:

TEST [PTsecurity] LDAP ASN1 1-byte length encoded found
TEST [PTsecurity] LDAP ASN1 2-byte length encoded found
TEST [PTsecurity] LDAP ASN1 4-byte length encoded found

Все дело оказывается в том, как кодируются длины отдельных полей в сообщениях LDAP. Байт x в последовательности байтов 30 8x yy yy yy отвечает за длину поля длины в байтах. Например, последовательность 30 82 00 02 кодирует два байта поля длины 00 02. Таким образом, участнику требовалось попробовать поля другой длины и обнаружить, что IDS не срабатывает на поле длиной 3 байта. Флаг лежит в ответе среди полей namingContexts. Таск предполагал единственное решение, и лишь двое справились с заданием.

Результаты:

1-е место: @vos — Apple Watch Series 6 + рюкзак
2-е место: @psih1337 — денежное вознаграждение + рюкзак
3-е место: @Abr1k0s — рюкзак

Теги:
Хабы:
Всего голосов 4: ↑4 и ↓0+4
Комментарии0

Публикации

Информация

Сайт
www.ptsecurity.com
Дата регистрации
Дата основания
2002
Численность
1 001–5 000 человек
Местоположение
Россия