// Безопасность

Малварь добралась до Terraform Registry: связанные с КНДР группы превращают ваш IaC-пайплайн в канал доставки

cover terraform registry malware

Впервые атакующие использовали публичный Terraform Registry от HashiCorp для распространения вредоносного ПО. Два вредоносных Terraform-провайдера и два Go-модуля доставили имплант на Go, который общается со своими операторами через смарт-контракт в блокчейне и Slack-бот, а кампания увязывается с Graphalgo, операцией с атрибуцией на Северную Корею, впервые задокументированной в феврале. Счётчики загрузок провайдеров пока небольшие, но суть в самом векторе: если отравленная зависимость может войти через ваш infrastructure-as-code, она входит с прямым выходом на ваши продакшен-креды.

Именно этот шов между деплой-тулингом и живой инфраструктурой атакующие сейчас и прощупывают. Вредоносный npm-пакет заражает ноутбук разработчика. Вредоносный Terraform-провайдер выполняется внутри процесса, который провижинит ваше облако. Это не один и тот же радиус поражения. Мы уже разбирали похожую логику на примере компрометации MemTensor: там тоже атакующие целили не в приложение, а в то, что его собирает и деплоит.

Что было опубликовано

По данным Aikido, раскрывшей активность, вредоносные пакеты были такими:

  • Terraform-провайдеры: gocommunity-io/dockerd (222 загрузки) и kreuzwenker/docker (1 449 загрузок).
  • Go-модули: gocommunity.io/orderedbtree и gogets.dev/btreex.

Обратите внимание на нейминг. dockerd и docker — это имена, близкие к тайпсквоттингу, сделанные под легитимный контейнерный тулинг, ровно то, что инженер, настраивающий контейнерную инфраструктуру, может схватить не глядя. Оба делят инфраструктуру с параллельной волной вредоносных npm-пакетов, помеченных на этой неделе Checkmarx, JFrog и SafeDep, включая indexed-btree, mathsbase, mathmain, math-universe, modern-events, quick-events, crypto-hasher, events-router, sort-btree, graphcore-js и graphlib-js. Если любое из этих имён есть в вашем дереве зависимостей, считайте это попаданием и читайте раздел реагирования ниже.

Почему Terraform-провайдер — худшее место для малвари, чем npm-пакет

Вот момент, над которым стоит задуматься. Aikido назвала Terraform-вектор новым, но неудивительным, и логика прямая: провайдер даёт более прямой путь к критичным продакшен-кредам. Подумайте, где Terraform-код реально выполняется. Он выполняется в вашем CI/CD-пайплайне или на машине оператора, держа ровно те учётные данные, что нужны для создания и удаления реальной инфраструктуры: облачные API-ключи, токены облачного провайдера, секреты для всего, что он провижинит. Провайдер — это код, который Terraform выполняет со всем этим в досягаемости. Малвари, приземлившейся там, не нужна эскалация или латеральное перемещение, чтобы добраться до ценного. Ценное уже в окружении, с которого она стартует.

И это не разовый эксперимент. Буквально на прошлой неделе SentinelOne описала отдельный связанный с Северной Кореей кластер, TraderTraitor, использующий оружейные Terraform lock-файлы для доставки Rust-бэкдоров из подконтрольных атакующим реестров провайдеров. Две связанные с КНДР кампании, тянущиеся к Terraform в одном временном окне, — это уже тот паттерн, что перестаёт быть совпадением. Как выразился исследователь Socket, у этих групп есть история переноса сработавшей техники между кампаниями, и реестры Terraform могут стать следующим каналом распространения, который они масштабируют.

Как имплант связывается с домом: два канала C2, оба сложно убить

Имплант на Go, доставляемый через Terraform и Go-пути, — это порт, который делит блокчейн- и Slack-инфраструктуру с npm-версией, и работает он на двух каналах command-and-control. Именно этот дизайн отмечает его как целевую, хорошо ресурсированную операцию, а не товарный криминальный софт.

При запуске он снимает отпечаток хоста, собирая аппаратные характеристики, ОС, hostname и наличие Node.js, затем отправляет этот check-in в Slack-канал атакующего через API. Дальше:

  • Slack-канал: имплант опрашивает эндпоинт conversations.history каждые 10 секунд и пересобирает передачи файлов из последовательности пакетов start, chunk и end. Slack-бот-токен как C2 растворяется в обычном корпоративном трафике, потому что исходящий HTTPS к Slack большинство egress-правил не флагает.
  • Блокчейн dead drop: Go-порт тянет зашифрованные команды из смарт-контракта Ethereum в тестнете Arbitrum Sepolia, используя захардкоженный адрес контракта и опрашивая каждые 3 секунды. Полученные команды исполняются как Go или JavaScript. Тейкдауна для смарт-контракта не существует, так что этот канал нельзя просто изъять, как домен.

Операторы наложили сверху реальную криптографическую дисциплину. Имплант генерирует эфемерную пару ключей и выводит общие ключи, комбинируя её с двумя публичными ключами группы, так что заражённые хосты могут делить каналы, не раскрывая C2-трафик и не сливая сообщения одной жертвы другой. Каждый клиент потребляет каждое сообщение и молча делает no-op на всём, что не может расшифровать. Исследователи восстановили имплант, но не тот код, что доставляется позже через эти каналы, а значит полный набор действий, выполняемых на жертвах, всё ещё неизвестен. Читайте это как предупреждение, а не как отбой: «мы не смогли восстановить пейлоад второй стадии» — это не «второй стадии не было».

Как жертвы вообще попадают под удар

Доставка опирается на социальную инженерию не меньше, чем на реестр. Сценарий Graphalgo подходит к разработчикам через LinkedIn, Facebook и объявления на джоб-бордах, выдавая себя за несуществующие Web3-компании, а затем просит цель выполнить задачу по кодингу, построенную вокруг безобидного на вид GitHub-репозитория, который подтягивает вредоносную зависимость. В нескольких пакетах пейлоад расшифровывается только когда жертва выполняет конкретную криптографическую операцию, решая линейную систему с одной определённой матрицей, что одновременно сужает исполнение до намеченных целей и мешает исследователям, нашедшим бэкенд без соответствующего фронтенда.

Этот же паттерн с фейковым собеседованием расползается. Проект Rust предупредил в этом месяце о продолжающейся кампании против участников rust-lang и владельцев популярных крейтов, где видеозвонок ради якобы работы или контракта используется, чтобы заставить цель что-то установить (фейковый «недостающий аудиокодек») или вставить команду из буфера обмена. Предупреждение Rust пересекается с кампанией Contagious Interview, тоже завязанной на Северную Корею. Общая нить через всё это: первичный доступ — это человек, которого убедили выполнить код, а реестр пакетов лишь механизм доставки.

Что делать

Единого патча здесь нет, потому что экспозиция — это класс зависимостей, а не версионный баг. Конкретные шаги:

  • Проверьте свои Terraform-провайдеры и модули против названного списка. Если gocommunity-io/dockerd, kreuzwenker/docker, gocommunity.io/orderedbtree или gogets.dev/btreex встречаются где-либо в вашем IaC, считайте окружение, которое их выполняло, скомпрометированным.
  • Проверьте npm-дерево на помеченные пакеты из списка выше, поскольку они делят ту же инфраструктуру оператора.
  • Проведите ротацию всех кредов, до которых мог дотянуться затронутый пайплайн или машина. Для Terraform это облачные API-ключи, токены провайдера и любой секрет, к которому имел доступ plan. Учитывая, что весь смысл Terraform-вектора в близости к продакшен-кредам, считайте, что их увели первыми.
  • Следите за egress на паттерны C2. Неожиданные исходящие вызовы к эндпоинтам Slack API с билд-агента или любой трафик к RPC-эндпоинтам тестнета Arbitrum Sepolia с инфраструктуры, которой нечего делать с блокчейном, — это сильные сигналы. Нормальные билд-серверы не опрашивают conversations.history каждые 10 секунд. Если не уверены, что ваша команда вообще заметит такой паттерн, регулярный DevSecOps-аудит CI/CD находит это быстрее, чем ожидание инцидента.
  • Пиньте и проверяйте инфраструктурные зависимости как продакшен-код. Провайдеры и модули из незнакомых неймспейсов заслуживают той же проверки, что и любой сторонний пакет, а низкие счётчики загрузок у провайдера с именем, мимикрирующим под популярный тулинг, — это красный флаг, а не повод расслабиться. Ту же дисциплину стоит применять к IaC, что и к обычному коду — именно это закрывает аудит исходного кода.
  • Считайте незапрошенные собеседования, требующие выполнить код, враждебными. Если «тестовое задание» или звонок просят разработчика склонировать и запустить репозиторий, установить кодек или вставить команду, это и есть вектор первичного доступа во всём этом семействе кампаний. Внедряйте MFA и проверяйте аккаунты на неожиданные входы. Если подозреваете, что кто-то из команды уже выполнил такую задачу, это повод сразу подключить incident response, а не разбираться своими силами.

Итог

Разговор о цепочке поставок в основном крутился вокруг npm и PyPI, потому что именно там был объём. Это смещает границу. Terraform-провайдеры помещают код атакующего внутрь процесса, который держит ваши инфраструктурные креды, а это более короткий путь к реальному ущербу, чем отравленная зависимость приложения, и способная, связанная с государством группа уже использовала этот путь дважды за две недели. Цифры загрузок сегодня маленькие. Масштабируется именно техника. Проверяйте инфраструктурные зависимости с той же серьёзностью, что и прикладные, ротируйте всё, до чего могли дотянуться затронутые пайплайны, и относитесь к слишком хорошему, чтобы быть правдой, собеседованию как к атаке, которой оно обычно и является. Если хотите проверить, что ваш IaC-пайплайн реально закрыт, а не выглядит закрытым, для этого у нас есть отдельный пентест инфраструктуры, а разбор уже произошедшего инцидента — через анализ вредоносной активности.

← назад в блог