Злоумышленники применяют новую тактику в кампании, направленной на использование открытых API Docker

security IOC

Исследователи безопасности Datadog недавно столкнулись с новой кампанией, направленной на конечные точки Docker API, открытые для публичного доступа без аутентификации, с целью распространения вредоносного ПО для криптоджекинга. Наблюдаемые тактики, методы и процедуры (TTP) похожи на те, что были замечены в Spinning YARN, другой кампании, обнаруженной в марте 2024 года компанией Cado Security. На основе анализа этих двух кампаний и инфраструктуры, лежащей в их основе, Datadog с высокой степенью уверенности предположили, что эти кампании связаны между собой.

Spinning YARN и подобные кампании часто трудно отличить только по телеметрии. Злоумышленники склонны повторять названия полезных нагрузок, даже если сами полезные нагрузки были обновлены или полностью заменены. Это делает анализ отдельных полезных нагрузок необходимым для получения полного представления об эволюции кампании.

Zzhbot Malware IOCs

Анализ атаки

Первоначальный доступ

Кампания начинается с того, что злоумышленник сканирует интернет в поисках хостов с открытым портом 2375 (порт Docker по умолчанию). После обнаружения подходящего узла начинается его эксплуатация с помощью обычных действий по разведке Docker, а именно запроса версии узла Docker перед попыткой его компрометации. Для этого злоумышленники выполняют команду docker version. В результате на конечную точку /v1.16/version отправляется HTTP GET-запрос, а затем злоумышленнику возвращается ответ, содержащий информацию о сервере.

Эта процедура дает злоумышленнику понять, что хост Docker доступен и отвечает на команды из открытого интернета. После подтверждения злоумышленник переходит к этапу эксплуатации, пытаясь породить контейнер Alpine Linux и используя параметр Binds конфигурации хоста Docker, привязать к контейнеру корневой каталог самого хоста Docker.

Фрагмент команды, используемой для порождения контейнера Alpine и привязки корневого каталога хоста (/) к точке монтирования внутри контейнера (/mnt).

Если это удается, злоумышленник повышает свои привилегии за счет доступа к базовой файловой системе хоста Docker через каталог /mnt внутри контейнера.

Наряду с определением образа контейнера и параметров конфигурации хоста злоумышленник выполняет команду shell (см. ниже) в самом контейнере. Эта команда использует утилиту оболочки Linux chroot для установки корня последующих процессов в каталог /mnt (в котором смонтирована базовая файловая система).

В той же команде в /usr/bin/vurl записывается сценарий оболочки в кодировке base64, а в /etc/crontab и /etc/cron.d/zzh сохраняется задание cron. Эти задания получают полезную нагрузку второго этапа с помощью исполняемого файла vurl (подробнее об этом ниже) и обеспечивают ее постоянное выполнение.

vurl (оболочка)

Для получения полезной нагрузки в ходе кампании злоумышленник использует две утилиты-загрузчика, обе с именем vurl (вероятно, по мотивам curl). В этом разделе мы рассмотрим первую полезную нагрузку vurl. Вторая будет рассмотрена в следующем разделе.

Первая полезная нагрузка vurl похожа на ту, что была найдена в оригинальной кампании Spinning YARN, с одним небольшим отличием: включением жестко закодированной строки агента пользователя (zzhbot). Полезная нагрузка состоит из сценария оболочки для подключения к контролируемому злоумышленником командно-контрольному (C2) серверу через файл устройства /dev/tcp и выполнения HTTP GET-запроса для получения дополнительных исполняемых файлов с сервера.

Если вы попытаетесь получить полезную нагрузку, не указав этот пользовательский агент, сервер вернет ошибку HTTP 404 (файл не найден). Требование указать пользовательский агент zzhbot, скорее всего, является попыткой злоумышленника ограничить получение полезной нагрузки хостами, скомпрометированными вредоносной программой.

Действия по достижению цели

После того как злоумышленник получил начальный доступ и добился выполнения через cron, следующим этапом кампании является получение и выполнение нового shell-скрипта-b.sh.

Этот скрипт содержит закодированный в base64 tar-архив нового двоичного файла с именем vurl. Сценарий декодирует и извлекает этот двоичный файл в /usr/bin/vurl, перезаписывая существующую версию сценария оболочки, а затем получает и выполняет один из двух сценариев оболочки -ar.sh или ai.sh.

vurl (двоичный файл)

В соответствии с бинарными полезными нагрузками оригинальной кампании, эта обновленная версия vurl скомпилирована из Go-кода и имеет ту же функциональность, что и ее эквивалент shell-сценарий, включая использование строки агента пользователя zzhbot.

От версии shell-скрипта этот двоичный файл отличается использованием жестко закодированных доменов C2. Когда вызывается двоичный файл vurl, в качестве аргумента ему передается URL. Домен в этом URL затем переписывается в один из двух контролируемых злоумышленниками C2-доменов: b.9-9-11[.]com или, если первый недоступен, b.9-9-12[.]com.

Двоичный файл vurl подключается к IP-адресу, на котором расположен домен C2, с помощью системного вызова connect() и отправляет тот же GET-запрос, что и сценарий оболочки. Как и раньше, сервер C2 вернет код состояния 200 и разрешит загрузку запрошенной полезной нагрузки только в том случае, если пользовательский агент установлен на zzhbot.

С обновленным бинарным файлом vurl вредоносная программа использует его для получения файла ar.sh, если он запущен под пользователем root, или ai.sh, если он запущен под обычным пользователем. На момент написания статьи полезная нагрузка ai.sh больше не передавалась, что делает вероятным предположение злоумышленника о том, что пользователь действительно является root.

Обратите внимание на использование доменов bing.com и google.com в качестве попытки обфусцировать домены доставки полезной нагрузки. Они переписываются на C2 злоумышленника с помощью бинарного файла vurl, как описано выше.

Несмотря на попытку обфусцировать домены доставки полезной нагрузки с помощью этой техники переписывания URL-адресов, злоумышленник раскрыл по крайней мере один из них на этапе первоначального доступа. Вредоносное задание cron, используемое для получения b.sh, содержит URL в base64-кодировке, который, конечно же, легко декодируется.

На этом этапе злоумышленник использует полезную нагрузку ar.sh для продолжения своих действий на объекте. Эта полезная нагрузка похожа на предыдущую версию Spinning YARN, и ниже приводится краткое описание ее функциональности

  • Определяет рабочий каталог /var/tmp/.222 (для хранения дополнительной полезной нагрузки).
  • Установите различные инструменты для компиляции кода и сканирования интернета
  • Удалите существующие записи cron
  • Ослабьте систему, отключив брандмауэры, очистив историю оболочки и предотвратив добавление новых строк в файл истории
  • Скомпилировать open source process hider libprocesshider при доставке и зарегистрировать его в динамическом компоновщике. Такое поведение также было замечено в нашем недавнем блоге Анализ двойника TeamTNT
  • Удалите агенты мониторинга, связанные с поставщиками облачных услуг, такими как Tencent и Alibaba Cloud
  • Очистить различные файлы журналов, включая syslog, messages, auth.log, boot.log, dmesg и т. д.
  • Получите и выполните следующую полезную нагрузку, chkstart

chkstart

Как уже говорилось выше, ar.sh извлекает и выполняет новый двоичный файл с именем chkstart. Это еще один двоичный файл Go, выступающий в качестве инструмента для настройки хоста на удаленный доступ, постоянного выполнения основной полезной нагрузки и загрузки дополнительных полезных нагрузок для продолжения цепочки выполнения. Этот двоичный файл отсутствует в публичных отчетах о подобных кампаниях, что позволяет предположить, что это новый инструмент, который развертывает злоумышленник.

В оригинальной кампании Spinning YARN большая часть функциональности chkstart выполнялась с помощью shell-скриптов. Перенос этой функциональности в Go-код может говорить о том, что злоумышленник пытается усложнить процесс анализа, поскольку статический анализ скомпилированного кода значительно сложнее, чем shell-скриптов. Также это может быть попыткой воспользоваться некоторыми возможностями Go, включая кросс-компиляцию, нативные тесты и сильную типизацию.

Как и в случае с оригинальной кампанией Spinning YARN, разработчик не позаботился о том, чтобы удалить двоичные файлы Go после компиляции, оставив нетронутой отладочную информацию DWARF. Это облегчает статический анализ, так как эта информация может помочь исследователю понять назначение бинарного файла.

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

Цель этой проверки - определить, был ли хост уже скомпрометирован вредоносным ПО. Если уже было установлено соединение с одним из жестко заданных поддоменов m, chkstart сообщит об этом в stdout и завершит процесс.

Если хост еще не скомпрометирован, вредоносная программа приступает к извлечению tar-архива с дополнительными полезными нагрузками для использования на следующем этапе. Затем он определяет новый массив URL-адресов (показан в следующем маркированном списке) и строку агента пользователя zzhbot и вызывает еще одну вспомогательную функцию downloadFile.

Эта функция downloadFile используется для загрузки ранее упомянутого tar-архива m.tar, содержащего дополнительную полезную нагрузку, из нового массива жестко закодированных URL. Примеры этих URL приведены ниже:

Если m.tar доступен по одному из этих URL, архив сохраняется по жестко заданному пути /var/tmp/.222, содержимое извлекается (подробнее об этом позже), и каталог /var/tmp/.222 становится исполняемым.

Регистрация стойкости

После извлечения архива дополнительных полезных нагрузок двоичный файл chkstart приступает к регистрации постоянства для нового двоичного файла с именем top.

Сначала chkstart выведет список файлов модулей systemd, выполнив команду systemctl --type=service list-unit-files. Вывод этой команды затем фильтруется для поиска результатов со строкой enabled, указывающей на то, что служба, определенная файлом юнитов, в настоящее время загружена и запущена.

Из полученных файлов модулей вредоносная программа находит путь к самому файлу через вывод systemctl show -p FragmentPath <имя службы>.

На следующем этапе с помощью этих путей к файлам выполняется поиск содержимого файлов модулей с помощью grep и определяется наличие директивы ExecStart=. Systemd использует эту директиву для определения пользовательской команды, которая будет выполняться после загрузки службы. В качестве примера значения можно привести путь к двоичному файлу, который вы хотите запустить в качестве службы.

Для файлов модулей с директивой ExecStart= systemd также позволяет определить дополнительную команду, которая будет выполняться после завершения команды ExecStart=. Она задается с помощью директивы ExecStartPost=. Вредоносная программа злоупотребляет этой возможностью, вставляя в файл юнитов строку ExecStartPost=/var/tmp/.222/top, в результате чего двоичный файл top выполняется каждый раз при загрузке службы.

На ванильном экземпляре Amazon Linux EC2 вредоносная программа определила /usr/lib/systemd/system/amazon-ssm-agent.service и /usr/lib/systemd/system/atd.service в качестве кандидатов на модификацию.

Пример содержимого модифицированного amazon-ssm-agent.service можно увидеть ниже:

Злоумышленник также использует chkstart для обновления конфигурации демона SSH, добавляя следующую строку:

AuthorizedKeysFile .ssh/authorized_keys .ssh/.ssh/zzhkeys

Это гарантирует, что открытые ключи, находящиеся в .ssh/authorized_keys и .ssh/.ssh/zzhkeys, могут быть использованы SSH-сервером для аутентификации. Затем вредоносная программа записывает контролируемый злоумышленником ключ в /root/.ssh/authorized_keys и /root/.ssh/.ssh/zzhkeys.

Перехват ресурсов

На этом этапе злоумышленник добился постоянного выполнения двоичного файла (с именем top) и - при условии, что SSH запущен, находится в открытом доступе и включена аутентификация с открытым ключом - получил доступ к взломанному хосту через SSH.

В отличие от предыдущих бинарных полезных нагрузок, top является "зачищенным", что означает, что разработчик попытался завуалировать его функциональность. Кроме того, он скомпилирован из кода на C++, а не на Go.

Несмотря на эти отличия, сам бинарник довольно неинтересен. Анализ показывает, что это пользовательская сборка майнера XMRig, с жестко закодированной конфигурацией, заложенной в сам бинарник. Это раскрывает цель кампании: захват ресурсов хоста Docker для добычи криптовалюты XMRig.

Подробная информация о конфигурации XMRig, извлеченной из top, приведена в разделе "Признаки компрометации" ниже. Следует отметить использование доменов m.9-9-11[.]com, m.9-9-12[.]com, m.9-9-13[.]com и m.9-9-14[.]com в качестве пользовательских майнинговых пулов. Это указывает на то, что злоумышленник использует поддомен b для размещения полезной нагрузки, а поддомен m - для размещения майнинговых пулов.

Латеральное перемещение

После запуска майнера XMRig на скомпрометированных узлах злоумышленники развертывают новую полезную нагрузку под названием exeremo и используют ее для бокового перемещения на дополнительные узлы.

exeremo - еще один пример переноса вредоносной функциональности, ранее встречавшейся в shell-скриптах, в код на языке Go. Этот двоичный файл представляет собой еще одну неизвестную полезную нагрузку из обновленной кампании и пытается выполнить следующие действия:

  • Определить связанные SSH-серверы и распространить на них вредоносную программу
  • Добавить маркер заражения на хост
  • Выполнить дополнительный сценарий оболочки (s.sh).

exeremo включает в себя несколько функций, предназначенных для извлечения имен пользователей, хостов и закрытых ключей, используемых в исходящих SSH-соединениях со скомпрометированного сервера.

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

Функция перехода Назначение Команда(и) оболочки
getUsers Извлекает имена пользователей SSH из файлов истории оболочки. cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep " @" |grep -vw " cp" | grep -vw " mv" | grep -vw " cd " | grep -vw " nano" | grep -v grep | grep -E " (ssh|scp)" |tr ':' ' ' | awk -F '@' '{print $1}'|awk '{print $NF}'|sort -k1|uniq
getUniqueHosts Извлечение хостов SSH из истории оболочки, файлов конфигурации SSH и known_hosts cat ~/.ssh/config /home/*/.ssh/config /root/.ssh/config | grep HostName | awk -F " HostName" '{print $2}'
cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep -E " (ssh|scp)" | grep -oP " ([0-9]{1,3}\.){3}[0-9]{1,3}"
cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep -E " (ssh|scp)" | tr ':' ' ' | awk -F '@' '{print $2}' | awk '{print $1}
cat /etc/hosts | grep -vw " 0.0.0.0" | grep -vw " 127.0.1.1" | grep -vw " 127.0.0.1" | sed -r '/\n/!s/[0-9.]+/\n&amp;\n/;/^([0-9]{1,3}\.){3}[0-9]{1,3}\n/P;D' | awk '{print $1}'
cat ~/*/.ssh/known_hosts /home/*/.ssh/known_hosts /root/.ssh/known_hosts | grep -oP " ([0-9]{1,3}\.){3}[0-9]{1,3}" | uniq
getKeyList Извлечение SSH-ключей из истории оболочки и файлов конфигурации SSH. cat ~/.ssh/config /home/*/.ssh/config /root/.ssh/config | grep IdentityFile | awk -F " IdentityFile" '{print $2 }'
cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep -E " (ssh|scp)" | awk -F ' -i ' '{print $2}' | awk '{print $1}'
getPortList Поиск в истории оболочки доказательств выполнения команд SSH и извлечение обнаруженных имен пользователей echo " 22" | cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep -vw 'cp' | grep -vw 'mv' | grep -vw 'cd ' | grep -vw 'nano' | grep -v grep | grep -E '(ssh|scp)' | tr ':' ' ' | awk -F '-p' '{print $2}'
cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep " @" |grep -vw " cp" | grep -vw " mv" | grep -vw " cd " | grep -vw " nano" | grep -v grep | grep -E " (ssh|scp)" |tr ':' ' ' | awk -F '@' '{print $1}'|awk '{print $NF}'|sort -k1|uniq

Результаты этих команд сохраняются в памяти и используются для выполнения ar.sh на удаленных хостах с помощью удаленного вызова команд по SSH. Команда SSH, используемая для этого, имеет следующий вид:

 

Чтобы помочь в выявлении новых серверов Docker для эксплуатации, exeremo получает еще один полезный сценарий оболочки под названием s.sh. Он считывается в память и выполняется динамически благодаря коду из функции executeScriptFromURL. И снова эта функция использует строку агента пользователя zzhbot в результирующем HTTP-запросе.

s.sh: Стэйджер для pnscan, masscan и пользовательской утилиты обнаружения Docker

s.sh содержит код, схожий с shell-скриптами, использовавшимися в оригинальной кампании Spinning YARN. Он отвечает за установку различных инструментов сканирования, обычно используемых в облачных и Linux-вредоносных атаках, например pnscan и masscan.

Сценарий также создает каталог по пути /etc/.httpd/.... и копирует в него двоичный файл с именем sd (извлеченный из m.tar и проанализированный ниже), после чего переименовывает его в httpd. Это соглашение об именовании также использовалось в предыдущей кампании и, вероятно, является попыткой замаскировать результирующий процесс под HTTP-сервер httpd, часто встречающийся в системах Linux.

После переименования бинарного файла sd создается служба systemd по следующему пути для постоянного запуска бинарного файла при загрузке:

/etc/systemd/system/zzhr.service

Для этого выполняются следующие команды systemctl:

Дополнительные полезные нагрузки

Также были обнаружены следующие дополнительные полезные нагрузки, но их поведение схоже с образцами из оригинальной кампании, поэтому они не считаются новыми. Поэтому ниже мы приводим краткое описание их функциональности.
sd/httpd

Этот 64-битный двоичный файл Go ELF напоминает инструмент начального доступа к Docker (d.sh), о котором сообщала компания Cado Security в своем блоге о Spinning YARN. Вредоносная программа использует masscan для сканирования случайного сетевого префикса /8 в поисках уязвимых узлов Docker Engine.

После обнаружения таких узлов вредоносная программа использует zgrab для отправки команд разведки Docker, описанных в разделе "Первоначальный доступ" этого блога. Если разведка прошла успешно, вредоносная программа отправляет описанную ранее команду начального доступа в base64-кодировке, запуская заражение на новом хосте.
fkoths

Еще один 64-битный двоичный файл Go ELF, который, судя по всему, является обновленной версией полезной нагрузки fkoths, обнаруженной Cado. В этой полезной нагрузке ничего существенного не изменилось, ее основная цель - удалить все образы Docker, созданные вредоносной программой на этапе Initial Access, по сути, выполняя анти-форетику на хосте. Он также обновляет /etc/hosts/ для "черной дыры" запросов к реестру Docker, перенаправляя их на loopback-адрес.

Indicators of Compromise

IPv4

  • 107.189.7.84
  • 194.36.190.118
  • 206.189.204.54
  • 64.19.222.131

Domains

  • b.9-9-11.com
  • b.9-9-12.com
  • m.9-9-11.com
  • m.9-9-12.com
  • m.9-9-13.com
  • m.9-9-14.com
  • m.9-9-15.com
  • m.9-9-16.com
  • m.9-9-17.com
  • m.9-9-18.com
  • m.9-9-19.com
  • m.9-9-8.com

URLs

  • b.9-9-11.com/brysj/d/ai.sh
  • b.9-9-11.com/brysj/d/ar.sh
  • b.9-9-11.com/brysj/d/s.sh
  • b.9-9-11.com/brysj/m/m.tar

SHA256

  • 048a1fe62bcd51cbf91128012dc1c15f25b17133d241c25d6717c3caf766c1ec
  • 0d508268b3f6d3b5396d5d182e546e59311af1d4ebe03a7728e2fd2a212c008b
  • 12481d3fbcee0ed5aa8a9c8bc1aeb71bf9439cbddf68e8cd275c2a90b26ec0ad
  • 2063e682e631fc28d77b50b32494edf2cf37bcc1e85c6d0302b34fa2e30aa52f
  • 32dfb086e6719c20666f151d17a3fbfcbccf559d0a8f1b2b888175f1a4d8f8a8
  • 51de345f677f46595fc3bd747bfb61bc9ff130adcbec48f3401f8057c8702af9
  • 7044f839aecd91bc5e4deac327d0b41fdae9a8238a9b64510ff336e49ed92e08
  • 852a577b227aa856399ae836d9db15eee38a4f62301a8590f80a009ec29dad8a
  • b6ddd29b0f74c8cfbe429320e7f83427f8db67e829164b67b73ebbdcd75d162d
  • dcff5f9e748c915aeefce08991d924197aff7f2a0affda00bfb45cfa1919b641
  • f3925aad20636a17be343ff473e6acb86345bc82c6611daa2154e24cd5e670e8
  • f53b8f70f6aeb478781e17ffd16a0fbbe5a5a08b4c4c0597091bc3407794ed1b
  • fdda14d3bc993960991ac6c95964514444e730f04b76d607df6e59087761648d
SEC-1275-1
Добавить комментарий