В ходе реагирования на инцидент у одного из наших клиентов командой PT ESC CSIRT был обнаружен ранее неизвестный бэкдор, написанный на языке Go, который мы атрибутировали к группе ExCobalt.
ExCobalt — это киберпреступная группа, сосредоточенная на кибершпионаже и некоторые члены которой активны по крайней мере с 2016 года и, предположительно, состояли в небезызвестной группе Cobalt. Группа Cobalt атаковала кредитно-финансовые организации с целью кражи денежных средств. Отличительной особенностью группы Cobalt было использование инструмента CobInt, который и начала применять группа ExCobalt c 2022 года.
За последний год специалисты PT ESC фиксировали атаки и проводили расследования инцидентов, связанные с группой ExCobalt, в российских организациях из следующих секторов:
- Металлургия
- Телекоммуникации
- Горная промышленность
- Информационные технологии
- Государственные учреждения
- Разработка ПО
В данной статье мы расскажем о новом инструменте группы — GoRed, его эволюции, а также о некоторых тактиках, техниках и процедурах, которые использовала группа в своих атаках.
Начало исследования
В ходе расследования одного из инцидентов, который был зафиксирован в марте 2024 года на одном из Linux-хостов нашего клиента, был обнаружен файл с названием scrond, накрытый UPX (Ultimate Packer for eXecutables).
В данных этого распакованного сэмпла, который написан на языке Go, были найдены пути пакетов, содержащие подстроку red.team/go-red/. Этот факт позволяет предположить, что этот сэмпл является проприетарным инструментом с названием GoRed.
Поисследовав сайт, нам не удалось найти каких-то значимых связей с вредоносной активностью. И поэтому можно предположить, что домен red.team найденный в строках GoRed является локальным репозиторием с утилитами для тестирования на проникновение.
Возвращаясь к бэкдору GoRed, можно выделить следующий основной функционал:
- Возможность подключения оператора и выполнения команд, как у других С2-фреймворков, наподобие Cobalt Strike, Sliver и так далее.
- Использование RPC-протокола для коммуникации GoRed с С2-сервером.
- Использование DNS-/ICMP-туннелирования, WSS и Quic для коммуникации оператора с GoRed.
- Возможность получения учетных данных со скомпрометированных систем.
- Сбор различной информации со скомпрометированных систем, например данных об активных процессах, имя хоста, список сетевых интерфейсов, структура файловых систем и так далее.
- Разведка в сети жертвы с помощью различных команд.
- Сериализация, шифрование, архивирование и отправка собранных данных на специальный сервер, предназначенный для хранения скомпрометированных данных.
Полное техническое описание GoRed см. в разделе «Анализ GoRed».
Первая версия GoRed и другие обнаруженные инструменты злоумышленников
В процессе анализа GoRed мы обнаружили, что несколько версий программы мы уже встречали ранее во время реагирования на инциденты у ряда наших клиентов. Так, например, в июле 2023 года в ходе расследования инцидента в компании благодаря ошибке самих атакующих на их директориях были обнаружены несколько различных инструментов, включая самую первую версию GoRed.
Похожим образом в другом инциденте в октябре 2023 года мы обнаружили на открытых директориях инфраструктуры злоумышленников дополнительные инструменты. Краткое название и описание инструментов, найденных в ходе расследований, представлены в таблице ниже:
2586 | CVE-2022-2586: Уязвимость в ядре Linux, связанная с подделкой указателей в функции io_uring. Использовалась злоумышленниками для повышения привилегий и выполнения произвольного кода на уязвимой системе. | |
3156.zip | CVE-2021-3156: Уязвимость в программе sudo, известная как Baron Samedit. Она позволяет локальному пользователю выполнить произвольный код с правами суперпользователя, обходя стандартные меры безопасности. | |
4034 | Pwnkit — эксплойт для локального повышения привилегий через эксплуатацию уязвимости CVE-2021-4034. Уязвимость в утилите pkexec. Она позволяет локальным пользователям повысить свои привилегии до root, что может привести к полной компрометации системы. | |
traceme | Эксплойт для локального повышения привилегий через CVE-2019-13272. Уязвимость в Linux-ядре, в компоненте ptrace. Она позволяет пользователям с привилегиями CAP_SYS_PTRACE повысить свои привилегии до root, что может использоваться для выполнения произвольного кода на системе. | |
bitrix.zip | Архив с vote_agent.php и html_editor_action.php с RCE-эксплойтами для битрикса. Распространялись ранее в телеграм-каналах в июне 2022 года, а также упоминались в массовом дефейсе веб-сайтов РФ в мае 2023 года https://habr.com/ru/companies/ruvds/articles/739898/ | |
col | Первая версия бэкдора GoRed — v0.0.1 | |
fs | fscan - https://github.com/shadow1ng/fscan/ | |
get_wp-commentin.txt | Обфусцированный php | |
run | run — запускает заданный исполняемый файл от root. Предназначен для FreeBSD. Аналог sudo exec <заданный файл> | |
set | set — назначает root владельцем файла и дает ему права rwx (чтение, запись, исполнение). Предназначен для FreeBSD. Аналог chown <файл> 0; chmod <файл> 777. | |
install | Установщик вредоносного модуля для Apache 2.4 | |
install[drop] | install[drop] — содержит дроппер с бинарным файлом, запакованным UPX, который записывает в /usr/local/games/w, chown root:root, chmod 4755 | |
install[drop][upx] /usr/local/games/w | install[drop][upx] /usr/local/games/w — пытается исполнить следующую команду от root пользователя: (setuid(0); setgid(0); /bin/sh -c ...)) | |
k | k — содержит следующий набор базовых сетевых утилит и заменяет имя процесса на [kthr]: | |
curl | урезанный curl | |
socksd | прокси (socks4/5 с поддержкой user+pass) | |
shell | bind shell | |
host | резолв hostname через 8.8.8.8 | |
hash | md5/sha1/sha256 | |
gz | inflate/deflate | |
netcat | - | |
kit | sh-скрипт для установки kitsune. В данном случае использовалась переменная MEGATSUNE вместо KITSUNE. В качестве С2 использовались amd64.rpm-bin.link и pkg.dpkg-source.info | |
lock.zip | Часть репозитория вайпера-шифровальщика locker c read.me-файлом на русском языке | |
locker | Сам локер из lock.zip без конфигов | |
m | Mettle - https://github.com/rapid7/mettle | |
rev | bind shell, общий код с shell из k, меняет имя процесса на [kr] | |
sf | Бинарный файл под BSD | |
spark | Spark RAT | |
w.txt | WSO php-вебшелл — https://github.com/ndbrain/WSO | |
wef | Вариация клиентской части Reverse SSH https://github.com/NHAS/reverse_ssh | |
y.txt | php p0wny-shell | |
knife/k | Как и в случае с k, был найден с именем k на открытой директории, но на другом домене спустя несколько месяцев. Функционал является схожим, что позволяет говорить, что это является просто следующей версией. Является инструментом для управления скомпрометированным Linux-сервером. Имеет разнородный функционал, команды для выполнения задаются в командной строке. Обладает следующим функционалом: | |
sync | Обработчика команды нет, происходит segfault при ее вызове | |
curl <url> | Загружает содержимое с заданного url | |
socksd | Запускает socks-сервер | |
netcat | Обработчика команды нет, происходит segfault при ее вызове | |
host <host> | Пытается разрешить имя заданного хоста через dns-сервер 8.8.8.8:53 | |
hash <имя файла> | Вычисляет хеш заданного файла (доступны md5, sha1, sha256) | |
gz <имя файла> | Архивирует заданный файл | |
shell <опции> <ip-адрес:порт> | Удаленный шелл. Команда запускается со следующими возможными опциями: -l — слушать заданный адрес, -c — самостоятельно осуществить соединение к заданному адресу |
Помимо инструментов, полученных с директорий серверов злоумышленников, группа ExCobalt использовала следующие инструменты:
- Mimikatz
- procdump
- SMBExec
- Metasploit
- rsocx
Модифицированные версии стандартных утилит
Помимо вышеприведенных инструментов, обнаруженных на открытых директориях, в нескольких инцидентах мы также встречали модифицированные версии стандартных утилит Linux, которые впервые мы обнаружили в ноябре 2023 года.
Назначение модифицированных утилит можно разделить на две категории:
1. ps и htop — для сокрытия активного процесса core модуля gsocket, а также связанных с ним процессов из вывода терминала.
В качестве примера возьмем ps.
Модификация кода была произведена в функции simple_readproc.
Оригинальный код выглядит следующим образом:
Был добавлен следующий код:
В функции is_target_proc происходит следующая проверка на равенство имени с зашитыми именами вредоносных процессов:
И если проверка проходит, то вредоносный процесс с именами, представленными на рисунке ниже, не будет отображен в терминале.
2. ss и netstat — для сокрытия активного сетевого соединения core модуля gsocket из вывода терминала.
В качестве примера возьмем netstat.
Первая модификация кода была произведена в функции main.
Оригинальный код выглядит следующим образом:
Для начала был добавлен код, который считывает все C2 из секции данных в глобальную структуру:
Вторая модификация в функции tcp_do_one, начиная отсюда:
В код были добавлены проверки на имя вредоносного процесса и вредоносного соединения. Если проверка проходит, то процесс с одним из вшитых имен или сетевых соединений не будет отображен:
Связь с ExCobalt
В ноябре 2023 года мы рассказывали об атаках ExCobalt на российские компании.
В вышеупомянутом репорте мы упоминали домен lib.rpm-bin.link, при энумерации директорий которого было получено множество инструментов, описанных выше, в том числе col — первая версия GoRed.
Помимо этого, в одном из инцидентов, который произошел в марте 2024 года, мы наблюдали активность зараженных хостов, которые связывались с серверами злоумышленников, — get.rpm-bin.link и leo.rpm-bin.link. Помимо этого, GoRed использовал static_TransportConfig, в котором были следующие C2:
- leo.rpm-bin.link
- sula.rpm-bin.link
- lib.rest
- rosm.pro
В мае 2023 года исследователи из Bi.Zone выпускали разбор атак Sneaking Leprechaun и их инструментарий пересекается с найденными на открытых директориях файлами, которые описаны выше.
Также коллеги из Ростелеком Солар выпустили в мае 2024 года исследование про кластер активности Shedding Zmiy, которое тоже соотносится с группой ExCobalt. В кейсе 7 этого исследования описывается та же атака и сэмпл стиллера GoRed с С2 — pkg.collect.net.in, который они обозначили как Bulldog Backdoor.
Анализ GoRed
Прежде чем перейти к анализу актуальной версии бэкдора GoRed, приведем ретроспективный анализ эволюции бэкдора.
Найденные версии
Все найденные нами версии приведены в таблице ниже.
Версия | Описание |
v0.0.1 |
|
0.0.9 |
|
v0.0.9 |
|
v0.0.13 |
|
v0.0.23-10-g4528ef3 |
|
v0.1.3-4-g68с293d | Данная версия упоминается только в докладе Солар, мы ее не встречали. |
v0.1.3-62-g4843e53 |
|
v0.1.4 | Изменений, в сравнении с предыдущей версией, — не обнаружено. |
В нашей статье мы проведем разбор актуальной версии v0.1.4.
Внутренние пакеты
Сначала опишем структуру внутренних пакетов и их назначение для понимания функциональных возможностей бэкдора GoRed, в данных которого были найдены пути пакетов, содержащие подстроку red.team/go-red/.
Пакет | Назначение |
red.team/go-red/config/ | Получение внутреннего и транспортного конфигов. |
red.team/go-red/bb/ | Обработка команд оператора. |
red.team/go-red/birdwatch/ | Мониторинг файловой системы. |
red.team/go-red/gecko/ | Протокол общения GoRed c C2. |
red.team/go-red/backend/ | Установка соединения с сервером для эксфильтрованных данных. |
red.team/go-red/collector/ | Сбор информации о системе. |
red.team/go-red/util/ | Различные вспомогательные утилиты. |
red.team/go-red/packer/ | Упаковка данных. |
red.team/go-red/proxy/ | Работа в режиме прокси. |
red.team/go-red/revshell/ | Работа в режиме обратного шелла. |
red.team/go-red/dns/ | Реализация dns-туннелирования. |
red.team/go-red/icmptunnel/ | Реализация icmp-туннелирования. |
Теперь можно перейти к непосредственному разбору. Для понимания работы потока управления ниже представлена его упрощенная схема.
1 — Начало выполнения
Поток управления базируется на command line (далее cli). Но, прежде чем передать управление cli, будут проинициализированы несколько команд, описанных далее:
- команда service.
- подкоманда gecko.
Первой будет проинициализирована команда service, которая осуществляет закрепление в системе. Структура команды GoRed для cli выглядит следующим образом:
struct cli_Command
{
string Name;
_slice_string Aliases;
string Usage;
string UsageText;
string Description;
string ArgsUsage;
string Category;
PTR_cli_BashCompleteFunc BashComplete;
PTR_cli_BeforeFunc Before;
PTR_cli_AfterFunc After;
PTR_cli_ActionFunc Action;
PTR_cli_OnUsageErrorFunc OnUsageError;
_slice__ptr_cli_Command Subcommands;
_slice_cli_Flag Flags;
cli_FlagCategories flagCategories;
bool SkipFlagParsing;
bool HideHelp;
bool HideHelpCommand;
bool Hidden;
bool UseShortOptionHandling;
string HelpName;
_slice_string commandNamePath;
string CustomHelpTemplate;
cli_CommandCategories categories;
bool isRoot;
cli_separatorSpec separator;
};
С точки зрения идентификации выполняемых команд самые интересные поля данной структуры следующие:
- Name — имя команды.
- Usage — описание команды.
- Action — функция, которая будет выполнена при вызове команды.
- Subcommands — подкоманды для текущей команды.
Далее будет проинициализирована структура самой cli в переменную app.
Структура app выглядит следующим образом:
struct cli_App
{
string Name;
string HelpName;
string Usage;
string UsageText;
string ArgsUsage;
string Version;
string Description;
string DefaultCommand;
_slice__ptr_cli_Command Commands;
_slice_cli_Flag Flags;
bool EnableBashCompletion;
bool HideHelp;
bool HideHelpCommand;
bool HideVersion;
cli_CommandCategories categories;
cli_FlagCategories flagCategories;
PTR_cli_BashCompleteFunc BashComplete;
PTR_cli_BeforeFunc Before;
PTR_cli_AfterFunc After;
PTR_cli_ActionFunc Action;
PTR_cli_CommandNotFoundFunc CommandNotFound;
PTR_cli_OnUsageErrorFunc OnUsageError;
PTR_cli_InvalidFlagAccessFunc InvalidFlagAccessHandler;
time_Time Compiled;
_slice__ptr_cli_Author Authors;
string Copyright;
io_Reader Reader;
io_Writer Writer;
io_Writer ErrWriter;
PTR_cli_ExitErrHandlerFunc ExitErrHandler;
map_string_interface_ Metadata;
PTR_func_map_string_string ExtraInfo;
string CustomAppHelpTemplate;
string SliceFlagSeparator;
bool DisableSliceFlagSeparator;
bool UseShortOptionHandling;
bool Suggest;
bool AllowExtFlags;
bool SkipFlagParsing;
bool didSetup;
cli_separatorSpec separator;
_ptr_cli_Command rootCommand;
};
И здесь также самыми информативными для идентификации команд полями являются следующие:
- Name — имя текущей команды.
- Action — функция, которая будет выполнена.
- Commands — подкоманды текущей команды.
А также будет инициализировано поле Commands для структуры app.
После идет получение поля Logging из структуры embedded_Config, которая будет описана в разделе ниже. После этого поток управления переходит к cli.
2 — Закрепление в системе
Первая команда, которая будет выполняться, — service. Она осуществляет закрепление в системе. В качестве параметров может принимать следующие значения:
Параметр | Назначение |
no-service | Просто переходит к выполнению команд cli. |
uninstall | Удаление сервиса. |
restart | Перезапуск сервиса. |
В случае если нет ни одного параметра из таблицы выше, то закрепляется как сервис с полученным именем в качестве аргумента. В качестве присутствия в скомпрометированной системе создает переменные окружения, имена которых начинаются с BB, например:
- BB_WS
- BB_QUIC
- BB_ICMP
- BB_DNS
- BB_START_DELAY
3 — Инициализация режима маяка
После поток управления будет передан команде gecko. Данная команда является входной точкой для работы GoRed в режиме маяка.
В качестве параметров может принимать следующие значения:
Параметр | Назначение |
wss | Использование в качестве протокола коммуникации оператора с GoRed. |
quic | |
icmp | |
dns | |
background | Будет ли команда добавлена как фоновая. |
start-delay | Задержка при коммуникации с C2. |
В зависимости от полученного протокола в качестве параметра, достает C2 из транспортной конфигурации, структура которого будет описана в разделе ниже. После он начинает инициализацию функционала режима маяка.
Для идентификации жертвы сначала генерирует ее ID, который является хеш-суммой MD5 от MAC-адресов и имени компьютера (как в случае с Hellhounds: операция Lahat). Полученная хеш-сумма будет добавлена в одно из полей структуры client, в которой хранятся все нужные данные для общения с С2.
4 — Установка первоначального соединения
После инициализации GoRed необходимо установить соединение с C2. Количество попыток для соединения реализуется за счет пакета backoff.
Поток исполнения стартует функцию для регистрации функционала режима маяка, а после идет инициализация команд для cli.
Для регистрации используется протокол RPC, данные из структуры model_Beacon будут отправлены на сервер, для аутентификации на котором будут использованы данные из структуры model_Auth.
struct model_RegisterBeaconRequest
{
model_Beacon Beacon;
model_Auth Auth;
};
struct model_Beacon
{
string ID;
string Hostname;
string ClientIPs;
_slice_string Tags;
string OS;
string Username;
};
struct model_Auth
{
string Token;
uuid_UUID ClientID;
string Transport;
};
Поля структур, приведенных выше, имеют следующие назначения.
Поле | Назначение | |
Beacon | Структура, содержащая информацию о жертве. | |
Поле | Назначение | |
ID | ID жертвы. | |
Hostname | Имя хоста жертвы. | |
ClientIPs | IP жертвы. | |
Tags | Тег жертвы. | |
OS | Операционная система жертвы. | |
Username | Имя пользователя жертвы. | |
Auth | Структура, содержащая данные для аутентификации. | |
Поле | Назначение | |
Token | Токен для аутентификации. | |
ClientID | ID клиента. | |
Transport | Используемый протокол. |
После регистрации GoRed запускает команду для мониторинга файловой системы — birdwatch.
Затем поток исполнения устанавливает период отстука GoRed в режиме маяка к C2.
После поток исполнения запускает команду для мониторинга файла паролей, хранящихся в /etc/shadow/.
И, в конце концов, поток исполнения инициализирует все доступные команды и входит в режим heartbeat.
5 — Режим получения и исполнения команд
На финальном этапе инициализации GoRed входит в режим прослушивания команд от оператора, которые он инициализировал ранее. Может выполнять как системные команды, так и встроенные. Также присутствует функция установки команды как фоновой.
6 — Общение в режиме маяка
Общение GoRed в режиме маяка с C2 осуществляется через RPC-протокол.
Для общения по RPC-протоколу он регистрирует свой кодек.
В зарегистрированном кодеке при отправке происходит сериализация данных через cbor и шифрование через AES-256-GCM (поле Secret в embedded_Config), а при получении происходит обратный процесс.
Конфиги
Внутри GoRed содержится 2 блока конфигураций — встроенная и транспортная.
Встроенная конфигурация
Является конфигурацией самого GoRed. Он закодирован base64, также сериализирован msgpack.
Для версий v0.0.23-10-g4528ef3 — v0.1.4 структура встроенной конфигурации следующая:
struct embedded_Config
{
string Logging;
string Token;
uuid_UUID UserID;
uuid_UUID ClientID;
string ClientKey;
string Version;
_slice_string Tags;
_slice_string Args;
string Secret;
_ptr_url_URL BackendAddress;
_ptr_url_URL ProxyAddress;
};
Назначения полей встроенной конфигурации следующие.
Поле | Назначение |
Logging | Осуществляется ли логирование действий и в каком формате.
|
Token | Сгенерированный JWT для RPC. |
UserID | UUID для JWT в поле payload. При использовании RPC. |
ClientID | Уникальный идентификатор для эксфильтрованных данных жертвы. |
ClientKey | Ключ, который нужен для генерации JWT (HS256) при эксфильтрации данных. |
Version | Версия GoRed. |
Tags | Тег жертвы. |
Args | Аргументы GoRed. |
Secret | Ключ для шифрования или дешифрования AES256-GCM, передаваемых или получаемых данных через RPC. |
BackendAddress | Адрес отдельного сервера для эксфильтрации данных. |
ProxyAddress | Список адресов прокси при эксфильтрации данных. |
Структура конфигурации для версий 0.0.9 — v0.0.13.
struct embedded_Config
{
bool Debug;
string Token;
uuid_UUID ClientID;
string ClientKey;
string Version;
_slice_string Tags;
string Secret;
string BasicAuthLogin;
string BasicAuthPass;
_ptr_url_URL BackendAddress;
_ptr_url_URL ProxyAddress;
};
Назначения полей этой версии встроенной конфигурации следующие.
Поле | Назначение |
Debug | Осуществляется ли логирование действий и в каком формате.
|
BasicAuthLogin | Логин, используемый для аутентификации при использовании команды curl. |
BasicAuthPass | Пароль, используемый для аутентификации при использовании команды curl. |
Встроенная конфигурация для версии v0.0.1.
struct embedded_Config
{
bool Debug;
uuid_UUID ClientID;
string ClientKey;
string Version;
_ptr_url_URL BackendAddress;
};
Скрипт для получения полей встроенной конфигурации, на языке Go.
package main
import (
"encoding/base64"
"fmt"
"net/url"
"github.com/google/uuid"
"github.com/vmihailenco/msgpack/v5"
)
type embedded_Config struct {
Logging string
Token string
UserID uuid.UUID
ClientID uuid.UUID
ClientKey string
Version string
Tags []string
Args []string
Secret string
BackendAddress* url.URL
ProxyAddress* url.URL
}
const config = `...`
func main() {
var item map[string]any
data, _ : = base64.StdEncoding.DecodeString(config)
err : = msgpack.Unmarshal(data, &item)
if err != nil{
panic(err)
}
fmt.Print("Logging: ")
fmt.Println(item["Logging"])
fmt.Print("Token: ")
fmt.Println(item["Token"])
fmt.Print("UserID: ")
fmt.Println(uuid.UUID(item["UserID"].([]byte)))
fmt.Print("ClientID: ")
fmt.Println(uuid.UUID(item["ClientID"].([]byte)))
fmt.Print("ClientKey: ")
fmt.Println(item["ClientKey"])
fmt.Print("Version: ")
fmt.Println(item["Version"])
fmt.Print("Tags: ")
fmt.Println(item["Tags"])
fmt.Print("Args: ")
fmt.Println(item["Args"])
fmt.Print("Secret: ")
fmt.Println(item["Secret"])
fmt.Print("BackendAddress: ")
fmt.Println(string(item["BackendAddress"].([]byte)))
fmt.Print("ProxyAddress: ")
fmt.Println(item["ProxyAddress"])
}
Скрипт для получения полей встроенной конфигурации, на языке Python.
import msgpack
import base64
s = base64.b64decode('...')
config = msgpack.unpackb(s, raw = False)
print(config)
Транспортная конфигурация
Транспортная конфигурация имеет следующий вид.
Структура транспортной конфигурации следующая.
struct static_TransportConfig
{
static_Transport Revsh;
static_Transport RPC;
static_Transport Proxy;
};
struct static_Transport
{
_ptr_static_Address WS;
_ptr_static_Address QUIC;
_ptr_static_Address ICMP;
_ptr_static_Address DNS;
_ptr_static_Address TCP;
};
struct static_Address
{
string Domain;
string BackupIP;
signed __int64 Port;
string Proto;
};
Поля транспортной конфигурации следующие.
Поле | Назначение |
Revsh | Адреса для подключения оператора по обратному шеллу. |
RPC | Адреса для отстука GoRed в режиме маяка через RPC. |
Proxy | Адреса для использования GoRed в режиме прокси. |
Поля транспортной конфигурации следующие.
Поле | Назначение |
Domain | Домен для подключения. |
BackupIP | IP для подключения, в случае если невозможно зарезолвить домен. |
Port | Порт для подключения. |
Proto | Протокол подключения. |
Протоколы общения
У GoRed есть несколько протоколов для общения с оператором.
Протокол | Реализация |
ws | Реализует подключение через протокол websockets. |
quic | Реализует подключение через протокол quic. |
icmp | Реализует подключение через icmp-туннелирование. |
dns | Реализует подключение через dns-туннелирование. |
DNS
DNS-туннелирование в GoRed может быть как через base64, так и через base32. Данная опция выбирается на этапе компилирования.
Пример домена, который использовался в атаке, 8E1A4QB4OGA66RPJCHL72DJGCKRMIOR8CDN3EDJBDOOAEQ3FEDQ5UQB4OGA66RP.JCHL6EDJGCKRMIOR8CDN3EDJBDLJG.rosm[.]pro.
Фоновые команды
Фоновые команды — это команды, которые работают постоянно, некоторые из них можно добавлять или убирать из фоновых, в зависимости от условий в таблице ниже.
Команда | Описание |
birdwatch | Команда для отслеживания новых файлов в каталогах. Фоновая по умолчанию.
|
creds-watcher | Команда для отслеживания паролей. Фоновая по умолчанию. |
revsh-host | Команда для работы в режиме обратного шелла. Становится фоновой при ее выполнении.
|
rev-proxy | Команда для работы в режиме обратного прокси через SOCKS5. Становится фоновой при ее выполнении. |
rev-fwd | Команда для работы в режиме обратной переадресации портов. Становится фоновой при ее выполнении. |
Установка соединения в режиме rev-proxy и rev-fwd
Прежде чем выступать в роли сервера, GoRed должен проинициализировать вшитый сертификат в формате X.509 (как в случае с Hellhounds: Операция Lahat. Часть 2).
Также необходимо собрать информацию о хосте жертвы, выполнив функцию CollectHostInfo с рисунка выше. Тем самым получив структуру (за исключением поля Addr), представленную ниже.
struct proto_HostInfo
{
string Addr;
string OS;
string Username;
string Hostname;
_slice_string IPs;
};
Поля структуры имеют следующие назначения.
Поле | Назначение |
Addr | Целевой адрес для подключения, который передается в качестве параметра для команды. |
OS | Операционная система жертвы. |
Username | Имя пользователя жертвы. |
Hostname | Имя хоста жертвы. |
IPs | IP-адреса жертвы. |
Инициализация структуры для идентификации GoRed, который выступает в роли сервера.
Проинициализированная структура выглядит следующим образом.
struct proto_BinInfo
{
uuid_UUID ClientID;
string Token;
_slice_string Tags;
};
Поля структуры имеют следующие назначения.
Поле | Назначение |
ClientID | Для идентификации жертвы. |
Token | Сгенерированный JWT для RPC. |
Tags | Тег жертвы. |
Получив структуры proto_HostInfo и proto_BinInfo, которые используются в сообщении «приветствия», отправляемого GoRed на C2, адрес которого он получил из транспортного конфига. Структура «приветствия» выглядит следующим образом.
struct proto_MsgGreeting
{
proto_ConnectionMode Mode;
string MachineID;
proto_BinInfo BinInfo;
_ptr_proto_HostInfo HostInfo;
};
Поля структуры имеют следующие назначения.
Поле | Назначение |
Mode | Режимы работы могут быть следующие:
|
MachineID | ID компьютера жертвы. |
BinInfo | Структура, содержащая информацию о конфиге GoRed. |
HostInfo | Структура, содержащая информацию о жертве. |
Схема отправки приветствия для регистрации в качестве сервера выглядит следующим образом.
В ответ на «приветствие» сервер отправляет сообщение со следующей структурой.
struct proto_MsgGreetingResponse
{
string Greeting;
_ptr_proto_BinInfo BinInfo;
_ptr_proto_HostInfo HostInfo;
};
Если поле Greeting содержит строку welcome, то соединение считается успешным и GoRed начинает работать в режиме сервера, если же нет, то соединение не может быть установлено.
Вызываемые команды
Оператор взаимодействует с GoRed посредством команд.
Команда | Описание |
upload | Команда для эксфильтрации файлов. В качестве аргумента принимает путь до файла. |
download | Команда для инфильтрации файлов. В качестве аргумента принимает путь до файла. |
bg-list | Команда для вывода списка внутренних фоновых команд. |
bg-stop | Команда для отмены внутренней фоновой команды. В качестве одного из аргументов принимает ID команды. Также может остановить все фоновые команды. |
stealth | Команда для автоматического установления частоты heartbeat в большем диапазоне для большей скрытности.
|
emit-period | Команда для получения или задавания частоты heartbeat в ручном режиме. |
conn-providers | Команда для получения доступных в данной версии GoRed протоколов коммуникации. |
info | Команда для получения информации о жертве.
|
collect | Команда для сбора и эксфильтрации информации о системе (подробнее в разделе ниже). |
bb-update | Команда для обновления GoRed. Делает запрос GET по URL (переданного аргументом) и перезапускает GoRed с аргументом restart. |
bb-ps | Команда для получения статуса процесса, который был передан аргументом. |
bb-cat | Команда для чтения файла, который был передан аргументом. |
bb-find | Команда для поиска файлов, которые были переданы аргументом. |
bb-ls | Команда для отображения содержимого каталога, который был передан аргументом. |
bb-mkdir | Команда для создания каталога, который был передан аргументом. |
bb-pwd | Команда для получения текущей директории. |
bb-rm | Команда для удаления файла, который был передан аргументом. |
bb-wc | Команда для сбора информации о файле, который был передан аргументом.
|
bb-nmap | Команда для сканирования сети. В качестве аргумента принимает хост. |
bb-ping | Команда для ping внешнего хоста. В качестве аргумента принимает IP. |
bb-wget | Команда для получения файлов через HTTP. В качестве аргумента принимает URL и output в качестве параметра с именем файла в качестве аргумента. |
bb-curl | Команда, похожая на утилиту curl, но с ограниченной функциональностью. |
collect
Так как это команда для сбора информации о системе, ее данных и последующей эксфильтрации, мы решили описать ее подробнее.
Параметр | Назначение |
local-archive | Выбор алгоритма сжатия. Tar или gzip. |
skip-trees | Пропустить сбор информации о структуре файловой системы. |
skip-files | Пропустить сбор файлов. |
exec-timeout | Время для сбора файлов. |
Собираемая информация
Пример собираемой информации представлен на рисунке ниже.
Полный список собираемой информации приведен в таблице ниже.
Файл | Содержимое |
processes.json | Список процессов. |
envvars.json | Список переменных окружения. |
host.json | Информация о процессоре, оперативной памяти, установленной ОС, имени пользователя, имени группы. |
network_interfaces.json | Список сетевых интерфейсов. |
netstats.json | Список активных сетевых соединений. |
*.txt | Файлы, которые будут собраны в зависимости от значения полей в структуре model_CollectionConfig. |
hardware.json | Информация о железе. |
trees.json | Структура файловой системы. |
Эксфильтрация
Перед отправкой данных происходит сериализация с помощью msgpack и шифрование AES256-GCM (поле Secret в embedded_Config).
Далее, после архивации данных, используя метод POST, отправляет их на URL, который формируется из BackendAddress (поле из embedded_Config) + “/api/collection-result”.
Также присутствует возможность обновления структуры model_CollectionConfig, используя метод GET, отправляя запрос на URL, который формируется из BackendAddress (поле из embedded_Config) + “/api/config”.
Структура model_CollectionConfig является конфигом для команды collect и имеет следующие поля.
struct model_CollectionConfig
{
_slice__slice_string Commands;
_slice_string Files;
_slice_string TreePaths;
};
Поля структуры имеют следующие назначения.
Поле | Назначение |
Commands | Команда bb_files_*. |
Files | Файлы. |
TreePaths | Пути. |
Выводы
Группа ExCobalt продолжает демонстрировать высокий уровень активности и решительности в атаках на российские компании, постоянно пополняя свой инструментарий и усовершенствуя свои техники. Они не только разрабатывают новые методы атак, но и активно улучшают свои существующие инструменты, включая бэкдор GoRed.
Наблюдается тенденция к расширению возможностей и функциональности бэкдора GoRed, что указывает на стремление ExCobalt к более сложным и эффективным методам взлома и кибершпионажа. Это включает в себя расширение функционала сбора данных жертв и повышение скрытности как в системе, так и в коммуникациях с управляющими серверами.
Кроме того, ExCobalt демонстрирует гибкость и адаптивность, пополняя свой инструментарий патченными тулзами, что позволяет им эффективно преодолевать защитные меры и адаптироваться к изменениям методов защиты. Использование патченных тулзов свидетельствует о глубоком понимании ExCobalt слабых мест атакуемых компаний, а использование многочисленных уязвимостей позволяет им развивать сложные атаки на них.
В целом развитие ExCobalt и их инструментария, включая бэкдор GoRed и использование патченных тулзов, подчеркивает необходимость постоянного совершенствования методов обнаружения и защиты со стороны организаций и специалистов по кибербезопасности для борьбы с этой группой и подобными киберугрозами.
Авторы:
Владислав Лунин, старший специалист отдела исследования угроз информационной безопасности экспертного центра безопасности Positive Technologies.
Александр Бадаев, специалист отдела исследования угроз информационной безопасности экспертного центра безопасности Positive Technologies.
IOCs
Файловые индикаторы
Сетевые индикаторы
Файловые сигнатуры
rule PTESC_apt_linux_UA_Excobalt__RiskTool__PsPatched{
strings:
$s = "For more details see ps(1)."
$readproc_patched = {48 8B BB A8 02 00 00 48 ?? ?? 74 0DE8 ?? ?? ?? ?? 85 ?? 0F 85 81 05 00 00 48 8B BB 28 03 00 00 48 ?? ?? 74 0D E8 ?? ?? ?? ?? 85 C0 0F 85 68 05 00 00 41 8B 54 24 50 48 89 D8 85 D2 74 13 83 7B 04 02 0F 84 52 05 00 00 83 ?? ?? 0F 84 49 05 00 00}
condition:
( uint32be ( 0 ) == 0x7f454c46 ) and ( all of them )
}
rule PTESC_apt_linux_UA_Excobalt__RiskTool__NetstatPatched{
strings:
$s = "usage: netstat [-vWeenNcCF] [<Af>] -r"
$main_patched = {48 8D 05 ?? ?? ?? ?? 4A 8B ?? ?? 0F B6 [1-2] 8D 50 ?? 80 FA ?? 76 ?? 84 C0 74 ?? 66 0F EF C0 31 F6}
condition:
( uint32be ( 0 ) == 0x7f454c46 ) and ( all of them )
}
rule PTESC_apt_linux_UA_Excobalt__RiskTool__SsPatched{
strings:
$s = "Usage: ss [ OPTIONS ]"
$main_patched = {48 63 FD 48 8D 05 ?? ?? ?? ?? 4C 89 EE 83 C5 ?? 48 C1 E7 ?? BA ?? ?? ?? ?? 48 01 C7 E8 ?? ?? ?? ?? 83 FB ?? 0F 9E C0 83 FD ?? 0F 9E C2 48 83 C3 ?? 20 D0 0F 85 ?? ?? ?? ??}
condition:
( uint32be ( 0 ) == 0x7f454c46 ) and ( all of them )
}
rule PTESC_apt_linux_UA_Excobalt__RiskTool__HtopPatched{
strings:
$s = "/.htoprc"
$readproc_patched = {48 89 DF E8 ?? ?? ?? ?? 48 8B 7B ?? 48 85 FF 74 ?? E8 ?? ?? ?? ?? 85 C0 75 ?? 48 8B 7B ?? 48 85 FF 74 ?? E8 ?? ?? ?? ?? 85 C0 75 ??}
condition:
( uint32be ( 0 ) == 0x7f454c46 ) and ( all of them )
}
rule PTESC_apt_multi_UA_Excobalt__Backdoor__GoRed__Obf{
strings:
$s1 = ").Parse" ascii nocase
$s2 = ").MarshalBinary" ascii nocase
$s3 = ").UnmarshalBinary" ascii nocase
$s4 = ").Request" ascii nocase
$s5 = ").Connect" ascii nocase
$s6 = ").MarshalJSON" ascii nocase
$s7 = ").Hash" ascii nocase
$s8 = ").Add" ascii nocase
$s9 = ").Close" ascii nocase
$s10 = "JWT" ascii nocase
$s11 = "config" ascii nocase
$s12 = "GET" ascii nocase
$s13 = "POST" ascii nocase
$s14 = "a5674391" ascii nocase
$c1 = {0F B6 54 0C ? ? 0F B6 74 0C ? ? 29 D6 40 88 74 0C ? ? 48 FF ? ? 48 83 F9 ? ? 7C ? ? }
$c2 = {0F B6 54 04 ? ? 0F B6 74 04 ? ? 31 D6 40 88 74 04 ? ? 48 FF ? ? 66 0F 1F 44 00 ? ? 48 83 F8 ? ? 7C ? ? }
$c3 = {0F B6 54 0C ? ? 0F B6 74 0C ? ? 01 F2 88 54 0C ? ? 48 FF ? ? 48 83 F9 ? ? 7C ? ? }
condition:
((uint32be(0) == 0x7f454c46) or (uint16be(0) == 0x4d5a)) and (all of them)
}
rule PTESC_apt_multi_UA_Excobalt__Backdoor__GoRed{
strings:
$s1 = "embedded.GetConfig" ascii nocase
$s2 = "common.runInBackground" ascii nocase
$s3 = "common.run" ascii nocase
$s4 = "common.RunCommand" ascii nocase
$s5 = "revsh" ascii nocase
$s6 = "dns" ascii nocase
$s7 = "ws" ascii nocase
$s8 = "dump" ascii nocase
$s9 = "shell" ascii nocase
$s10 = "files" ascii nocase
condition :
((uint32be(0) == 0x7f454c46) or (uint16be(0) == 0x4d5a)) and (all of them)
}
MITRE TTPs
Вердикты продуктов Positive Technologies
PT Sandbox
apt_multi_UA_Excobalt__Backdoor__GoRed |
apt_multi_UA_Excobalt__Backdoor__GoRed__Obf |
apt_linux_UA_Excobalt__RiskTool__PsPatched |
apt_linux_UA_Excobalt__RiskTool__NetstatPatched |
apt_linux_UA_Excobalt__RiskTool__HtopPatched |
apt_linux_UA_Ruh8__Dropper__kit |
tool_multi_ZZ_WebShell__Backdoor__Generic__PHP |
tool_multi_ZZ_WebShell__Backdoor__PHP__Obfuscated |
tool_multi_ZZ_Gsocket__NetTool |
MaxPatrol SIEM
Unix_Boot_Modify (mod probe) |
Unix_System_Information_Discovery |
Unix_Connect_from_Suspicious_Dir |
Unix_Suspicious_Command |
PT NAD
BACKDOOR [PTsecurity] GoRed Request sid: 10011377 |
BACKDOOR [PTsecurity] GoRed Exfiltration sid: 10011378 |
ATTACK AD [PTsecurity] Anonymous SMB connect to IPC share sid: 10005876, 10005877 |
TOOLS [PTsecurity] .gs.thc.org domain resolve. Probably activity gsocket sid: 10009306 |
TOOLS [PTsecurity] gsocket server activity sid: 10009305 |
SUSPICIOUS [PTsecurity] Suspicious communication using UA go-external-ip & External IP Check sid: 10011380 |
POLICY [PTsecurity] HTTP Host header RFC2616 violation sid: 10011339 |
POLICY [PTsecurity] Unsuccessful SMB Port Scan External Network sid: 10001310, 10003655 |