![](https://habrastorage.org/getpro/habr/upload_files/c23/542/00b/c2354200b10d213385d477909ecd2e3c.png)
Привет, Хабр, на связи лаборатория кибербезопасности компании AP Security! Не так давно на нашем канале вышла статья по использованию фреймворка постэксплуатации Sliver C2 от Bishop Fox.
Сегодня мы представляем вам исследование компании Immersive Labs по детектированию и анализу нагрузок и туннелей взаимодействия Sliver.
Этот С2 всё сильнее набирает популярность, а значит специалисты по реагированию на инциденты должны быть всегда готовы столкнуться лицом к лицу с новыми техниками и инструментами. Приятного прочтения!
Sliver C2 представляет собой кроссплатформенный расширяемый фреймворк постэксплуатации, созданный командой Bishop Fox. Он написан преимущественно на языке Go, что делает его быстрым, переносимым и легко настраиваемым. Такая универсальность делает инструмент популярным в Red Team проектах.
Фреймворк Sliver C2 обладает возможностями, рассчитанными как на начинающих, так и на опытных пользователей. Одной из его особенностей является возможность генерировать динамические пэйлоады под разные ОС.
Что касается коммуникаций, то Sliver поддерживает широкий спектр протоколов, включая HTTP, HTTPS, DNS, TCP и WireGuard. Это обеспечивает гибкость и скрытность, а также возможность маскировки канала C2 под легитимный сетевой трафик.
Более подробно об использовании Sliver можно прочитать в нашей статье Sliver C2: Подробный туториал.
Одним словом, Sliver C2 в последнее время серьезно набирает популярность. Ниже приведена диаграмма использования различных фреймворков постэксплуатации в последние месяцы.
![](https://habrastorage.org/getpro/habr/upload_files/39a/397/280/39a39728055a29934384d94e0e41880c.png)
Threat hunting
Из-за роста популярности данного фреймворка, хакеры и пентестеры всё чаще используют его при проведении атак на инфраструктуру. Именно поэтому специалистам по реагированию на инциденты, участникам Blue Team и инженерам SOC важно знать методы обнаружения Sliver по различным артефактам в файловой системе, оперативной памяти и сетевом трафике.
В данном отчете подробно описываются технические методы обнаружения, которые можно использовать для выявления использования Sliver.
Целевая инфраструктура
Для захвата трафика и сбора артефактов, а в дальнейшем анализа маячков фреймворка был создан небольшой тестовый полигон, предназначенный для тестирования средств обнаружения и сбора логов. При этом наша микроинфраструтура должна была включать возможности EDR.
Endpoint Detection and Response (EDR) – продвинутая система безопасности, представляющая собой интегрированное решение для обеспечения безопасности конечных точек от потенциальных угроз. Технология сочетает в себе непрерывный мониторинг и сбор данных о хостах в режиме реального времени и решает проблему постоянного мониторинга и реагирования на сложные угрозы.
Полигон состоял из следующих основных элементов:
Хост-машина, которую мы контролировали для установки имплантата
Регистрация событий
Sysmon
Splunk
Ведение сетевого журнала
Полный захват пакетов
Ведение журнала DNS
EDR
Velociraptor
Сброс/восстановление
![](https://habrastorage.org/getpro/habr/upload_files/a76/e14/cb9/a76e14cb942003c942271d22fdf1c0c9.png)
Инфраструктура злоумышленника
После развертывания целевой инфраструктуры пора заняться развертыванием C2 сервера Sliver. В данном случае все было просто: всего лишь одна VPS на "белом" IP-адресе, что позволило легко открыть необходимые порты TCP, HTTP/S и DNS для диапазона.
Можно было бы развернуть C2 во внутренней сети, однако в этом случае у него был бы внутренний IP-адрес. Поэтому для большей реалистичности использовался отдельный сервер для инфраструктуры злоумышленника.
DNS
Для DNS была выбрана конфигурация Cloudflare, которая позволила установить DNS записи, необходимые для HTTP/S C2, и создать запись nameserver
для C2 без необходимости использования нескольких доменов.
![](https://habrastorage.org/getpro/habr/upload_files/c2e/d5a/088/c2ed5a088955f7ceb2c0a9639cb02c39.webp)
В данной конфигурации используются настройки по умолчанию, приведенные в wiki BishopFix по установке и настройке DNS.
Сервер Sliver C2
В данном исследовании не рассматривалась возможность использования фреймворка Sliver, поэтому было решено сделать подключение к серверу напрямую, а не использовать многопользовательский режим, который позволяет нескольким операторам управлять C2. Более традиционное развертывание выглядит следующим образом.
![](https://habrastorage.org/getpro/habr/upload_files/a18/34f/a03/a1834fa038194a51686c447c6d9d23a1.png)
В конфигурации вместо удаленных операторов был использован прямой консольный доступ к серверу C2.
Установка
Так как Sliver написан на GoLang, его установка предельно проста. Достаточно скачать необходимый исполняемый файл, дать ему права на выполнение и запустить.
![](https://habrastorage.org/getpro/habr/upload_files/ea3/bb2/7dd/ea3bb27dd51e98ddb6cd283ae82ffa83.png)
Запустив сервер Sliver C2, были также запущены локальные listeners
для HTTP и DNS.
Настройка
![](https://habrastorage.org/getpro/habr/upload_files/2d5/c03/aa5/2d5c03aa55f1f13f1c9a310fb6a2ddfb.png)
Теперь, когда listeners
запущены, необходимо создать маячки для отправки на хосты, чтобы инициировать первоначальную компрометацию.
![](https://habrastorage.org/getpro/habr/upload_files/675/473/d42/675473d4231df0199997870e0d776c75.png)
Доставка
В данном исследовании нас не интересуют продвинутые механизмы доставки. Поэтому для передачи полезной нагрузки клиенту использовалась простая команда python3 -m http.server
на хосте Sliver и команду PowerShell iwr
на целевом хосте.
![](https://habrastorage.org/getpro/habr/upload_files/975/05b/02e/97505b02ec9fd77f94ee730f2339e2c0.png)
Анализ
Итак, инфраструктура развернута, все средства настроены, нагрузка доставлена. Пришло время приступить к анализу. Маячки могут быть обфусцированы и модифицированы с помощью различных техник - их слишком много, чтобы описывать их в исследовании. В данном отчете представлены некоторые базовые методы обнаружения бинарных файлов, но основное внимание уделяется обнаружению имплантата в памяти или по протоколам C2.
Нагрузка
Пэйлоад был сгенерирован в виде скомпилированного двоичного файла на языке Go. Это делает его легко портируемым под разные ОС и архитектуры. Однако, из-за статической линковки средний размер файла составляет 16 Мб, а это далеко не маленькая цифра для полезной нагрузки C2. Для решения этой проблемы Sliver поддерживает использование других фреймворков и инструментов, таких как Metasploit, для создания более компактных совместимых нагрузок.
Обнаружение в памяти облегчается, поскольку весь двоичный файл Go должен быть распакован в память независимо от упаковки двоичного файла или поэтапной доставки.
Yara Rules для обнаружения исполняемого файла
Простое правило Yara использовалось для обнаружения немодифицированного импланта Sliver, созданного для Windows, Linux или MacOS.
![](https://habrastorage.org/getpro/habr/upload_files/648/482/ad5/648482ad54691e56187b92e2b5cf37b8.png)
Yara Rules для обнаружения нагрузки в памяти
Это правило предназначено для обнаружения Sliver, работающего в памяти; приведенное выше Yara правило не подходит для обнаружения в оперативной памяти, поскольку использует некоторые фиксированные смещения для уменьшения количества ложных срабатываний при сканировании файлов.
![](https://habrastorage.org/getpro/habr/upload_files/826/ec0/792/826ec0792e69a060a0f1135aaca85198.png)
Command & Control
Sliver имеет четыре основных протокола взаимодействия:
DNS
mTLS
WireGuard
HTTP(S) Весь трафик Sliver шифруется и в зависимости от протокола может использоваться дополнительное кодирование для усиления маскировки трафика.
DNS
При обмене данными через DNS маячок Sliver кодирует свои сообщения в запросы и ответы поддоменов. Практически, этот принцип ничем не отличается от стандартных методов DNS туннелирования.
![](https://habrastorage.org/getpro/habr/upload_files/75d/de6/aa6/75dde6aa6a41a1939b33a9298f479d5b.png)
Однако, Sliver отличается от большинства C2 тем, как упаковываются и кодируются данные, что позволяет передать гораздо больший объем данных в одном запросе.
Структура
Так как DNS не ориентирован на создание соединения, Sliver необходим способ отслеживания последовательности данных в закодированных пакетах. Для этого он использует protobuff.
Protocol Buffers (Protobuf) - это формат сериализации данных, разработанный компанией Google. Он эффективно и компактно хранит структурированные данные в двоичной форме, что позволяет быстрее передавать их по сети. Protobuf поддерживает широкий спектр выбранных языков программирования и является платформонезависимым, что означает, что программы, написанные с его использованием, могут быть легко перенесены на другие платформы.
![](https://habrastorage.org/getpro/habr/upload_files/9a9/a3c/52a/9a9a3c52a487a487d6ff59a5c0a36abb.png)
Кодирование
После того как сообщение упаковано в protobuf, его необходимо закодировать в строку поддомена. По умолчанию используется кодировка Base58 с возможностью перехода на Base32.
Для дополнительной маскировки Sliver также использует слегка измененные алфавиты для кодировки Base32 и Base58.
![](https://habrastorage.org/getpro/habr/upload_files/1c9/c4e/f8d/1c9c4ef8db838985080a40065b957c9e.png)
Обнаружение
Поскольку зашифрованная нагрузка ограничена 254 символами на поддомен, а количество символов в одном запросе ограничено, сервера C2 и маячки, использующие DNS, генерируют значительный трафик, сильно превышающий объем трафика других протоколов. Это может позволить легко обнаружить такой канал, если в инфраструктуре регистрируется DNS-трафик.
Ниже приведены примеры обнаружения DNS туннеля с помощью Kibana. Здесь показан счетчик событий после отправки 3-4 команд с С2 за 5 минут.
Kibana - программная панель визуализации данных, использующая Elastic. Kibana используется для мониторинга и анализа ИТ-инфраструктуры в составе Elastic Stack, в который помимо нее входят Elasticsearch и Logstash.
![](https://habrastorage.org/getpro/habr/upload_files/511/096/169/51109616953542e390a9dcf31c628e16.png)
![](https://habrastorage.org/getpro/habr/upload_files/0b8/da4/05a/0b8da405a30f443a038f4e81391d0a60.png)
HTTP(S)
Протокол взаимодействия идентичен для HTTP и HTTPS. Единственным отличием является использование шифрования, что требуется перехват TLS или ведение сетевого журнала на хосте с помощью Zeek или PacketBeat.
Важно отметить, что настройка параметров протокола HTTP в Sliver является весьма гибкой, и приведенная в исследовании информация относится к настройкам по умолчанию.
Структура
Sliver использует расширения файлов для определения типа запроса
.woff - Используется для стейджеров
.html - Обмен ключами
.js - Сообщения длинного опроса
.php - Сессионные сообщения
.png - Сообщения о закрытии сессии
Для каждого запроса создается случайный путь, который игнорируется и не имеет отношения ни к сообщению, ни к запросу. Однако существует фиксированное количество путей и имен файлов по умолчанию, что позволяет создавать некоторые типовые правила обнаружения.
![](https://habrastorage.org/getpro/habr/upload_files/f8b/691/be6/f8b691be6f609e5012fdddafcc8dc522.png)
Стоит еще раз отметить, что все эти параметры могут быть дополнительно сконфигурированы оператором C2.
Кодирование
Сообщения кодируются следующими методами:
![](https://habrastorage.org/getpro/habr/upload_files/a82/123/19f/a8212319fa2b551d84f625d41c0964c0.png)
Кодер выбирается случайным образом при каждой отправке нового сообщения. Используемый кодер кодируется как значение nonce
и добавляется в качестве параметра запроса к каждому HTTP-запросу. Например, по следующему URL-адресу можно легко определить, какой кодер используется, с помощью небольшого количества кода на языке Python.
![](https://habrastorage.org/getpro/habr/upload_files/a86/91d/14d/a8691d14d60e6621b38f18de56dd2625.png)
На выходе получим encoder_id
, равный 13. По таблице определяем, что использовался base64 с "кастомным" алфавитом.
Ниже приведены измененные алфавиты для кодировок Base32, 58, 64
![](https://habrastorage.org/getpro/habr/upload_files/47b/011/3bd/47b0113bd25a1243211e2bd731cff7a9.png)
Кодировка английскими словами
В качестве механизма кодирования в данном методе используются списки английских слов. Сами же слова при этом "захардкожены" в нагрузке, всего их 1420.
![](https://habrastorage.org/getpro/habr/upload_files/757/fce/d45/757fced450a4d62e739c8fbe14f0bff4.png)
Сами по себе слова не важны, для кодирования и декодирования используется позиция в списке или сумма символов в слове. Пример декодера, написанного на языке Python, приведен ниже.
![](https://habrastorage.org/getpro/habr/upload_files/d95/f00/978/d95f00978922e7d2f226a11a2db9882b.png)
Обнаружение
Если маячок настроен на использование HTTP или у вас есть возможность TLS-перехвата на прокси-сервере или пограничном маршрутизаторе, то эти для обнаружения туннеля Sliver можно использовать следующие правила для Snort.
![](https://habrastorage.org/getpro/habr/upload_files/f65/b5d/616/f65b5d6166a1b6ae9e4e4e26d44e50ab.png)
![](https://habrastorage.org/getpro/habr/upload_files/d18/77c/7e5/d1877c7e518329e24d982da284738c30.png)
Если собрать сетевые журналы с узлов инфраструктуры с помощью анализатора вроде Zeek или Packet Beat, то в журналах событий можно обнаружить те же закономерности.
![](https://habrastorage.org/getpro/habr/upload_files/b32/d70/0f5/b32d700f51a2047de3a0a69edfdf3895.png)
Шифрование
Процесс шифрования канала достаточно неплохо описан в официальной документации на GitHub. Здесь мы не будем рассматривать все детали, а лишь скажем, что каждое сообщение шифруется индивидуально с использованием сеансового ключа, генерируемого нагрузкой при каждом отдельном запуске.
Сеансовые ключи
Сеансовый ключ в защищенном виде передается на C2 сервер Sliver. Однако если вы сможете извлечь ключ из памяти процесса Sliver, то сможете расшифровать любой перехваченный сетевой трафик, как и в случае с любым другим фреймворком постэксплуатации.
Чтобы найти ключ шифрования в памяти, необходимо в первую очередь выяснить, как он выглядит и существует ли он где-то в структуре данных, которую можно разобрать. Самый простой способ сделать это - узнать ключ и затем искать его в памяти.
Этого оказалось достаточно просто добиться. Поскольку Sliver имеет открытый исходный код, мы взяли копию исходного кода и модифицировали его так, чтобы он выдавал сеансовые ключи в открытом виде.
![](https://habrastorage.org/getpro/habr/upload_files/9cc/c3d/31b/9ccc3d31b07e152aceb0cde18b74171c.png)
После внесения изменений в код мы смогли скомпилировать новую версию C2 сервера и запустить ее на нашей инфраструктуре злоумышленника.
После этого, когда маячок подключался обратно, мы получали сеансовый ключ в открытом виде.
![](https://habrastorage.org/getpro/habr/upload_files/e5d/5f3/697/e5d5f3697dbbba18c94e650cb642c0dc.png)
Память процесса
Далее необходимо было определить процесс под которым запущен маячок. Это довольно просто сделать, Velociraptor и ранее созданное Yara-правило.
![](https://habrastorage.org/getpro/habr/upload_files/983/389/259/98338925987c8c510cd9a4d7bfccf16d.png)
Запускаем сканирование и через некоторое время получаем дамп вредоносного процесса.
![](https://habrastorage.org/getpro/habr/upload_files/071/d7b/bb5/071d7bbb59f620804a85a44ffe3b347d.png)
В качестве альтернативы, если вы знаете имя или PID процесса, можно воспользоваться стандартной утилитой procdump из пакета Sysinternals.
После получения дампа памяти процесса, попробуем найти в нем ключ шифрования.
Извлечение ключей
Используя ключи, полученные на C2 сервере Sliver после подключения маячка, был просканирован дамп процесса с целью найти их.
![](https://habrastorage.org/getpro/habr/upload_files/352/54f/b5a/35254fb5a03ab6dc6f132396edc6c64a.png)
Хорошая новость заключается в том, что ключ всегда можно найти в памяти активного процесса. Плохая же заключается в том, что он не находится в фиксированном месте, а значит будет затруднительно прочитать это значение.
Запуск одного и того же процесса позволил выявить закономерность.
Весь процесс поиска закономерности состоял из следующих этапов:
Остановить запущенный процесс
Запустить процесс
Послать с сервера несколько команд на маячок
Подождать 1-2 минуты
Получить дамп процесса
Найти ключ, который отображается для каждой сессии
Перейти к 1-му шагу
Таким образом был найден паттерн
**00 00 [32 bytes key] ?? ?? ?? 00 C0 00 00**
Сканирование памяти по этому шаблону давало несколько тысяч результатов - 17 206 совпадений шаблонов для данного каждого захвата памяти. Однако быстрая проверка показала, что ключ находится в этом наборе совпадений.
В идеале нужно было уменьшить это число. Если бы количество результатов было достаточно мало, можно было бы перебрать ключ, получив зашифрованную нагрузку. Как же уменьшить количество результатов?
Сам сеансовый ключ получается из хэша SHA256 случайных байтов. Было выдвинуто предположение, что в любом сеансовом ключе не будет серии из трех последовательных байтов 0x00, и смогли сократить этот список всего до 38 возможных ключей.
Не исключено, что сеансовый ключ может содержать последовательность из нескольких нулевых байтов, но вероятность этого крайне мала. Чтобы доказать это, был написан небольшой скрипт, который генерировал 10 млн. случайных значений SHA256 и затем проверял их на наличие возможных цепочек нулевых байтов.
![](https://habrastorage.org/getpro/habr/upload_files/df8/ff6/5e5/df8ff65e56375cc862d0eb36c6142b6c.png)
![](https://habrastorage.org/getpro/habr/upload_files/bde/198/7a1/bde1987a1fd15cd049b8a6a4c9b1a49b.png)
Как видно из 30 миллионов сгенерированных значений SHA256, вероятность появления трех или четырех последовательных нулевых байтов составляет 0,0004%.
Расшифровка трафика
Если бы возможно было перехватить трафик с помощью сниффера, перехвата журналов DNS или даже извлечения фрагментов из памяти процессов, то информации для расшифровки было бы достаточно.
Все инструменты и скрипты, используемые для разбора PCAP-файлов и расшифровки трафика, были опубликованы в репозитории Immersive Labs.
DNS туннели
Журналы DNS, пожалуй, проще всего собирать либо из файлов PCAP, либо из журналов событий и SIEM.
Используя скрипт sliver_pcap_parser.py
из репозитория GitHub, было указано доменное имя, и скрипт извлек все возможные закодированные значения, готовые для следующего шага - расшифровки.
![](https://habrastorage.org/getpro/habr/upload_files/872/e29/576/872e295766cf778ecdac899c1fe9d760.png)
HTTP туннели
Этот же скрипт может анализировать HTTP-запросы и ответы на предмет возможной закодированной нагрузки. Полезная нагрузка HTTP записывается в JSON-файл, содержащий все необходимые поля для обработки сценарием расшифровки.
![](https://habrastorage.org/getpro/habr/upload_files/ca0/78a/4c0/ca078a4c0124d1be5460f20014ea3dfd.png)
Память процесса
В зависимости от времени, прошедшего с момента наблюдения до получения дампа памяти, в нем могут быть обнаружены части сессии. В репозитории GitHub можно найти Python-скрипт sliver_memdump_parser.py
для сканирования дампа процесса на наличие таких фрагментов.
Декодирование и расшифровка
Получив дамп процесса и закодированные части сессии, извлеченные из подходящего источника, была произведена попытка декодировать и расшифровать данные сессии.
Сначала скрипт сканировал дамп памяти процесса на наличие всех возможных ключей сессии, затем проверял каждый ключ, используя предоставленную нагрузку, пока не добивался успешного декодирования.
![](https://habrastorage.org/getpro/habr/upload_files/635/cf3/383/635cf338332e01c7f1d8fb9edf6069e2.png)
Данные сообщения представлены в виде структуры protobuf
.
Заключение
В последнее время специалисты по реагированию на инциденты всё чаще встречаются с Sliver C2. Методы разбора атак с использованием Sliver во многом схожи с анализом инцидентов, в которых в качестве фреймворка постэксплуатации применялся не менее известный коммерческий Cobalt Strike, однако везде есть свои особенности.
Также стоит упомянуть, что для анализа Cobalt давно существуют целые микролаборатории и наборы скриптов, заточенные именно под него, в то время как под Sliver только начинают появляться инструменты, что существенно усложняет анализ.