Соревнования по обходу IDS впервые проводились на международном форуме Positive Hack Days 2019. Участникам нужно было исследовать сегмент сети из пяти узлов, после чего либо эксплуатировать уязвимость сервиса, либо выполнить заданное условие (например, отправить определенный HTTP-ответ) и таким образом получить флаг.
Найти эксплойт было легко, но IDS усложнила задачу: система стояла между участниками и узлами и проверяла каждый сетевой пакет. Злоумышленники могли видеть на приборной панели, блокировала ли подпись их соединение.
Ниже я подробно расскажу о самих задачах и разберу их решения.
100.64.0.11 — Стойки
Первой нодой по количеству людей, решивших задачу, стал Struts. После сканирования портов Nmap мы находим сервис Apache Struts на порту 8080.# nmap -Pn -sV -p1-10000 100.64.0.11 631/tcp open ipp CUPS 2.1 8005/tcp open mxi? 8009/tcp open ajp13 Apache Jserv (Protocol v1.3) 8080/tcp open http Apache Tomcat/Coyote JSP engine 1.1
Уязвимость Apache Struts исчезла в 2017 году: с помощью OGNL-инъекции злоумышленник мог выполнить любой код Struts без авторизации.
Эесть эксплойт, например, на GitHub , но перехватывается IDS: [Drop] [**] [1:1001:1] Apache Struts2 OGNL inj in header (CVE-2017-5638) [**]
Сам код подписи участникам недоступен, но из сообщения в логах можно понять механизм его работы.
В этом случае сигнатура обнаружила внедрение OGNL в HTTP: GET /showcase.action HTTP/1.1
Accept-Encoding: identity
Host: 100.64.0.11:8080
Content-Type: %{(#_='multipart/form-data').
Если вы исследуете поведение IDS, станет очевидно, что он улавливает комбинацию %{ в начале заголовка Content-Type. Есть несколько возможных решений:
- Участник @empty_jack попытался разбить комбинацию символов %{ с помощью своего собственного словаря фаззинга и, таким образом, нашел решение с помощью строки Content-Type: %${.
- Фазз самого HTTP-запроса.
Участник @c00lhax0r обнаружил, что нулевой символ в начале заголовка также обходит IDS: Content-Type: \0${.
- Большинство эксплойтов для CVE-2017-5638 вводят символ процента.
Но некоторые исследователи этой и предыдущих уязвимостей Apache Struts писать что инъекция может начинаться с % или $.
Таким образом, комбинация ${ обойдет сигнатуру IDS и выполнит код в системе.
Такое решение было задумано с самого начала.
100.64.0.10 - Солр
На порту 8983 стоял сервер Apache Solr, написанный на Java. $ nmap -Pn -sV -p1-10000 100.64.0.10
22/tcp open ssh (protocol 2.0)
8983/tcp open http Jetty
Эксплойт для Apache Solr 5.3.0 найти легко — CVE-2019-0192 .
Злоумышленник может подделать адрес сервера RMI в коллекции.
Для работы требуется фреймворк ysoserial, который генерирует цепочки Java-объектов (гаджетов) и доставляет их различными способами.
Например, с сервера JRMP.
Конечно, используя вышеупомянутый эксплойт напрямую, участники увидят срабатывание сигнатур IDS: [Drop] [**] [1:10002700:3001] ATTACK [PTsecurity] Java Object Deserialization RCE POP Chain (ysoserial Jdk7u21) [**]
Jdk7u21 — лишь одна из тридцати загрузок, и их выбор зависит от библиотек, используемых в уязвимом сервисе.
Цепочка гаджетов Jdk7u21 использует только стандартные классы из Java Development Kit версии 7u21, а цепочка CommonsCollections1 содержит классы из широко используемых Apache Common Collections 3.1. Злоумышленник заменяет адрес сервера RMI в коллекции Solr на свой, а затем запускает сервер JRMP. Solr запрашивает объект по адресу и получает вредоносный объект Java. После десериализации код выполняется на сервере.
Подпись активируется последовательностью классов в сериализованном объекте Java. Он передается с машины злоумышленника и начинается в трафике так:
Решение этой проблемы было простым.
Подпись явно относится к Jdk7u21. Чтобы обойти это, пришлось пробовать другие цепочки гаджетов.
Например, один из CommonsCollections. Подписей для других сетей в IDS не было.
Участник получит оболочку в системе и прочтет флаг.
Пять участников справились с заданием.
100.64.0.12 - САМР
Одно из самых сложных и интересных заданий конкурса.Это машина Windows с открытым портом 445. Флаг разделен на имена двух пользователей системы, и для выполнения задачи необходимо было получить список всех пользователей на узле Windows. Разумеется, MS17-010 и другие эксплоиты на этой машине не работали.
Пользователи могут быть перечислены, например, с помощью скриптов из Нмап или структура пакет : $ python samrdump.py 100.64.0.12
Impacket v0.9.15 - Copyright 2002-2016 Core Security Technologies
[*] Retrieving endpoint list from 100.64.0.12
[*] Trying protocol 445/SMB…
Found domain(s):
.
SAMR .
Builtin
[*] Looking up users in domain SAMR
[-] The NETBIOS connection with the remote host timed out.
[*] No entries received.
Оба скрипта делают запросы DCERPC к машине по порту 445. Но не все так просто: некоторые пакеты блокируются IDS, и на этот раз срабатывают две сигнатуры: [**] [1:2001:2] SAMR DCERPC Bind [**]
[Drop] [**] [1:2002:2] SAMR EnumDomainUsers Request [**]
Первый обнаруживает соединение со службой SAMR и только отмечает TCP-соединение флагом.
А второй запускается запросом EnumDomainUsers к сервису SAMR. У этого сервиса есть и другие способы получения пользователей: QueryDisplayInfo, QueryDisplayInfo2, QueryDisplayInfo3. Все они также были заблокированы подписями.
Протокол DCERPC и службы Windows предоставляют огромные возможности для удаленного управления узлами.
Этот протокол используется большинством известных инструментов, например PsExec или BloodHound. Сервис SAMR, то есть SAM Remote Protocol, позволяет работать с учетными записями на узле и, помимо прочего, узнавать список пользователей.
Для запроса EnumDomainUsers Impacket выполняет следующее:
Соединение DCERPC со службой SAMR устанавливается через SMB, и все дальнейшие запросы выполняются в контексте этой службы.
Подписи срабатывают на первом и последнем пакете со скриншота.
Я дал два совета по выполнению задачи:
Речь идет о протоколе DCERPC и о том, как устанавливаются соединения.
- Ваши попытки приводят к тому, что IDS генерирует 2 оповещения.
Посмотрите внимательно на первое.
- Какие команды подключения по этому протоколу вы знаете?
В списке доступных PDU команды Bind и Alter Context отвечают за подключение и изменение контекста, а вторая позволяет изменить текущий контекст, не разрывая соединения.
Для ее решения пришлось переписать логику скрипта samrdump:
- Сделайте привязку к другой службе, например с UUID 3919286a-b10c-11d0-9ba8-00c04fd92ef5.
- Используйте «Изменить контекст», чтобы переключиться на SAMR.
- Отправьте запрос EnumDomainUsers.
< dce.bind(samr.MSRPC_UUID_SAMR)
---
> dce.bind(uuid.uuidtup_to_bin(("3919286a-b10c-11d0-9ba8-00c04fd92ef5", "0.0")))
> dce.alter_ctx(samr.MSRPC_UUID_SAMR)
> dce._ctx = 1
Альтернативное решение предложил победитель конкурса @psih1337. Запрос EnumDomainUsers вернул список пользователей не по имени, а по SID (Security ID).
SID не является случайным числом.
Например, учетная запись LocalSystem имеет SID S-1-5-18, а для пользователей, созданных вручную, он начинается с 1000. Таким образом, перебрав вручную семена от 1000 до 2000, вы с большой долей вероятности сможете найти в системе нужные аккаунты.
Они были обнаружены под семенами 1008 и 1009. Решение этой задачи потребовало понимания протокола DCERPC и опыта исследования инфраструктур Windows. @psih1337 был единственным, кто решил эту проблему.
100.64.0.13 — DNSCAT
На порту 80 есть веб-страница с формой IP-адреса.
Если указать свой IP, то UDP приходит на 53 порт: 17:40:45.501553 IP 100.64.0.13.38730 > 100.64.0.187: 61936+ CNAME? dnscat.d2bc039ce800000000d6eae8eae3bf81fd84d1695f5888aba8dcec06d071.a73b3f0561ca4906d268214f4b70da1bdb50f75739ae0577139096732bf8.0d0a987ce23408bac15426a22e. (173)
17:40:45.501639 IP 100.64.0.187 > 100.64.0.13: ICMP 100.64.0.187 udp port domain unreachable, length 209
17:40:46.520457 IP 100.64.0.13.38730 > 100.64.0.187: 21842+ TXT? dnscat.7f4e039ce800000000d6eae8eae3bf81fd84d1695f5888aba8dcec06d071.a73b3f0561ca4906d268214f4b70da1bdb50f75739ae0577139096732bf8.0d0a987ce23408bac15426a22e. (173)
17:40:46.520546 IP 100.64.0.187 > 100.64.0.13: ICMP 100.64.0.187 udp port domain unreachable, length 209
Понятно, что это DNSCAT — инструмент для DNS-туннелей.
После указания IP-адреса в форме клиент DNSCAT пытается установить с ним соединение.
Если это сработает, сервер (то есть участник) получит шелл на соревновательной машине и вытащит флаг.
Конечно, если мы просто запустим сервер DNSCAT и попытаемся принять соединение, у нас ничего не получится: [Drop] [**] [1:4001:1] 'dnscat' string found in DNS response [**]
Сигнатура IDS срабатывает по строке «dnscat» в трафике с нашего сервера — об этом четко сказано в сообщении.
Запутывание или шифрование трафика также не сработает. Взглянув на клиентский код, мы обнаружим, что проверки в нем недостаточно строгие.
То есть ответ может вообще не содержать строки «dnscat»! Останется только удалить его из кода или заменить на лету утилитой NetSED. Гораздо проще сразу заменить, но патч для серверного кода я все равно предоставлю: diff -r dnscat2/server/libs/dnser.rb dnscat2_bypass/server/libs/dnser.rb
< segments << unpack("a#{len}")
> segments << [unpack("a#{len}")[0].
upcase] < name.split(/\.
/).
each do |segment| > name.upcase.split(/\.
/).
each do |segment|
diff -r dnscat2/server/tunnel_drivers/driver_dns.rb dnscat2_bypass/server/tunnel_drivers/driver_dns.rb
< response = (response == "" ? "dnscat" : ("dnscat." + response))
> response = (response == "" ? "dnsCat" : ("dnsCat." + response))
На конкурсе было пять решений этой задачи.
100.64.0.14 - ПОСТ
Никто не получил флага от этой гоночной машины.
Видим знакомую форму с IP-адресом.
Кто-то предлагает нам поучаствовать в тестировании новой вредоносной программы.
Среди ее нововведений — обход IDS неизвестным методом.
Для флага вам просто нужно отправить ему в ответ HTTP-заголовок «Server: ng1nx».
Будет жарко.
Как и ожидалось: получаем GET-запрос на свой IP и отправляем ответ, который блокируется IDS. [Drop] [**] [1:5002:1] 'ng1nx' Server header found. Malware shall not pass [**]
Вот подсказка:
Иногда задачи, которые кажутся сложными, оказываются самыми простыми.Что-то уязвимое прямо перед нашим носом — это IDS. На странице положительных результатов вы можете увидеть, что у нас открыт Suricata IDS.Если ничто не кажется уязвимым, возможно, вы что-то упускаете прямо у себя под носом?
Первая ссылка по запросу «Обход Suricata IDS» ведет на CVE-2018-6794 .
Эта уязвимость позволяет обойти проверку пакетов, нарушая нормальный поток TCP-квитирования и отправляя данные до завершения процесса.
Это выглядит так: Client -> [SYN] [Seq=0 Ack=0] -> Evil Server # 1/2
Client <- [SYN, ACK] [Seq=0 Ack=1] <- Evil Server # 2/2
Client <- [PSH, ACK] [Seq=1 Ack=1] <- Evil Server # Data here
Client <- [FIN, ACK] [Seq=83 Ack=1] <- Evil Server
Client -> [ACK] [Seq=1 Ack=84] -> Evil Server # 3/2
Client -> [PSH, ACK] [Seq=1 Ack= 4] -> Evil Server
Загрузите эксплойт, измените строку на «ng1nx», отключите RST-пакеты ядра и запустите его.
Как уже говорилось, флагов от этой машины никто не получил, хотя пара участников была близка к решению.
Заключение
На соревнования зарегистрировались 49 участников, 12 передали хотя бы один флаг.Интересно, что конкурсные задачи могут иметь сразу несколько решений, особенно задачи с протоколом SMB и DCERPC. Может быть, у вас есть свои идеи выполнения каких-то заданий? Первые места:
- 1 место: @psih1337
- 2 место: @webr0ck
- 3 место: @empty_jack
Спасибо всем участникам! В следующем году заданий разного уровня сложности будет еще больше.
Автор : Кирилл Шипулин, Positive Technologies Теги: #информационная безопасность #спортивное программирование #соревнования #ids #PHDays #PHDays #PHDays #PHDays #positive hackdays
-
Прямо Сейчас: Прокси-Серверы
19 Oct, 24 -
11 Вещей, Которые Я Узнал О Custdev
19 Oct, 24 -
Настоящая Тайна Золотого Миллиарда
19 Oct, 24 -
Платить Или Учить?
19 Oct, 24 -
Трансморферы. Самый Мощный Трэш
19 Oct, 24 -
Пост О Хабре И Добре
19 Oct, 24