Хакеры захватили 4837 аккаунтов GitHub и проверили доступ к 61 764 репозиториям. Как минимум в 1800 проектах вредоносный код смог запуститься и передать секретные данные злоумышленникам. Среди затронутых аккаунтов оказались даже связанные с правительствами США и Франции.
Массовая кампания wfx-loot началась 10 ноября. Используя похищенные учётные данные, атакующие получили возможность изменять чужие репозитории и запускать в них собственный код. Причём 10 431 проверочный запрос затронул проекты, которые не принадлежали взломанным пользователям. Доступ к ним существовал благодаря правам участников команд и организаций.
Среди скомпрометированных аккаунтов обнаружились учётные записи, связанные с американским Управлением общих служб GSA, французскими государственными структурами, компаниями из списка Fortune 100, а также проектами Nextcloud и WebdriverIO. Однако присутствие организации среди затронутых аккаунтов ещё не доказывает утечку её внутренних данных. Исследователи пока не установили полный перечень пострадавших.
Атака начиналась с безобидного на вид запроса на изменение кода под названием «docs: dependency audit notes». Злоумышленники создавали его из ветки wfx-docs, проверяя, позволяют ли украденные токены записывать файлы в репозиторий. Если проверка проходила успешно, они переходили к следующему этапу. На момент публикации исследования 92% таких запросов оставались открытыми. Владельцы большинства проектов, вероятно, даже не заметили посторонней активности.
Затем преступники внедряли примерно 1500 строк вредоносного сценария. Для этого использовались конвейеры CI/CD, которые автоматически собирают, проверяют и публикуют программное обеспечение. Вредоносный код добавляли в существующие задания GitHub Actions, помещали в отдельные временные файлы или подключали через механизм postinstall в npm. Последний вариант позволял запускать программу при обычной установке зависимостей.
Особенно интересным оказался обход защиты GitHub. Платформа задерживала подозрительные задания, непосредственно изменявшие конфигурацию автоматизации. Тогда атакующие стали прятать вредоносный сценарий в обычных файлах проекта. Уже существующие доверенные задания сами запускали его при выполнении npm install. Исследователи изучили журналы 19 репозиториев, где сценарий действительно выполнился. В 18 случаях программа сообщила об успешной отправке похищенных данных.
Вредонос собирал практически всё, до чего мог добраться на сборочном сервере. В перечень входили токены GitHub, ключи AWS, Azure и Google Cloud, SSH-ключи, пароли, переменные окружения, конфигурации Kubernetes и данные из памяти работающих процессов. Отдельно программа искала ключи сервисов OpenAI, Anthropic, Gemini, Hugging Face и инструментов разработки Cursor, Copilot и Codex. Кроме того, она копировала содержимое репозитория и сведения о последних коммитах.
Кражей паролей дело не ограничивалось. При наличии достаточных полномочий вредонос пытался закрепиться в облачной инфраструктуре. В AWS он мог создавать долгосрочные ключи доступа и изменять политики доверия ролей, разрешая подключение из посторонних аккаунтов. В Azure программа добавляла новые федеративные учётные данные с префиксом wfx-ci-. Благодаря этому злоумышленники потенциально сохраняли доступ даже после смены украденных паролей и токенов.
После сбора информации программа упаковывала данные в архив и отправляла их на серверы атакующих. В более поздних версиях появился канал передачи через Telegram. Закончив работу, злоумышленники возвращали исходные файлы, удаляли запуск GitHub Actions вместе с журналами и старались уложиться в минуту. Поэтому обычная проверка текущего состояния проекта могла ничего не показать. Иногда единственным заметным следом оставался пропущенный номер запуска автоматического задания.
Масштаб операции оказался значительно шире числа подтверждённых утечек. При анализе вредоносных коммитов специалисты SafeDep выявили 8093 репозитория, в которые атакующие успели внести изменения. Другая исследовательская группа обнаружила 28 500 внедрений вредоносного кода в 17 715 репозиториях. Эти оценки получены разными методами и не означают, что во всех перечисленных проектах программа успешно выполнилась. Точное число утечек остаётся неизвестным.
Атака затронула и распространение программных библиотек. Вредоносный сценарий попал в версию 3.14.3 пакета digitalelvis/neuronai-studio из Packagist, а также в файлы автоматизации нескольких выпусков Go-модулей. При этом заражение пакета не обязательно означает выполнение кода у каждого пользователя. Например, в исследованных версиях Go-модуля исходники программы и готовые бинарные файлы не изменялись, а вредонос находился только в конфигурации GitHub Actions.
У кампании обнаружилось пересечение с октябрьской атакой GhostAction, также использовавшей похищенные аккаунты разработчиков. В некоторых репозиториях новый вредонос внедряли непосредственно в файлы, оставшиеся после предыдущего заражения. Однако исследователи считают операции самостоятельными и предполагают участие разных злоумышленников. Происхождение первоначально похищенных учётных данных пока окончательно не установлено.
Владельцам репозиториев рекомендуют проверить наличие ветки wfx-docs, подозрительных запросов «docs: dependency audit notes», коммитов «ci: refresh build cache» и «chore: add ci helper», а также пропусков в истории запусков GitHub Actions. При обнаружении признаков компрометации необходимо отозвать украденные токены GitHub и проверить все проекты, к которым они предоставляли доступ. Если вредоносный сценарий выполнялся, следует заменить доступные ему секреты, проверить облачные роли AWS, федеративные учётные данные Azure и журналы действий в инфраструктуре.
Главная опасность wfx-loot заключается в том, что для массового заражения не потребовалось взламывать сам GitHub. Злоумышленникам хватило действующих учётных данных разработчиков и разрешений на изменение кода. После этого привычные инструменты автоматической сборки превращались в средство кражи корпоративных секретов, а очистка репозитория от вредоносных файлов уже не гарантировала прекращения доступа к облачной инфраструктуре.