npm-пакеты Red Hat Cloud Services скомпрометированы в результате атаки отравления цепочки поставок

iconMetaEra
Поделиться
Share IconShare IconShare IconShare IconShare IconShare IconCopy
AI summary iconСводка

expand icon
Согласно новостям из цепочки блоков от MetaEra, уязвимость безопасности была зафиксирована в нескольких пакетах npm, принадлежащих организации Red Hat Cloud Services. Система MistEye обнаружила 96 вредоносных версий в 32 пакетах, из которых три были проанализированы подробно. Вредоносный код в пакетах, таких как @redhat-cloud-services/frontend-components-config@6.11.3, выполняется во время установки через хук preinstall. Вредоносная программа, вариант Shai-Hulud, включает кражу учетных данных и эксплуатацию CI/CD. Злоумышленники использовали ROT/сдвиги Цезаря, AES-GCM и B5-шифрование для маскировки полезной нагрузки, которая распространяется через npm и рабочие процессы GitHub.

Контекст

Недавно система безопасности MistEye зафиксировала информацию о появлении аномальных версий нескольких npm-пакетов, принадлежащих организации Red Hat Cloud Services. В рамках данного инцидента затронуты 32 npm-пакета и 96 версий от этой организации. В данной статье проводится глубокий оффлайн-анализ трех локальных образцов: эти образцы не являются поддельными или схожими по написанию пакетами, а представляют собой настоящие версии пакетов с использованием scope @redhat-cloud-services; анализ исходного кода подтверждает, что в их tarball были встроены многоуровнево запутанные вредоносные загрузчики, автоматически активирующиеся на этапе установки.

После полного восстановления можно подтвердить, что эти три образца обладают исходным кодом для следующих функций: чтение памяти GitHub Actions Runner, сбор учетных данных из нескольких облаков и локальных систем, передача данных через GitHub API и dead-drop, инъекция в GitHub workflow, самораспространение через npm, персистентность через Claude Code / VS Code / systemd / LaunchAgent, противодействие Harden-Runner / StepSecurity, обнаружение EDR и средств безопасности. С точки зрения охвата возможностей, потенциально затронутыми объектами являются хосты разработчиков, CI/CD Runner, сборочные контейнеры, репозитории GitHub, рабочие процессы GitHub Actions, цепочки публикации npm и учетные данные облачной среды; фактический масштаб воздействия необходимо подтвердить с учетом журналов установки, аудита репозиториев и телеметрии платформы.

С точки зрения структуры кода, путей распространения и комбинации возможностей, это вредоносное программное обеспечение является вариантом Shai-Hulud.

MistEye ответ

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

После выявления инцидента отравления цепочки поставок npm-пакетов Red Hat Cloud Services и связанных вредоносных образцов система MistEye сгенерировала высокий уровень оповещения и провела системный анализ запутанной структуры, дешифровки полезной нагрузки, восстановления функциональности и IOC данной атаки.

(https://enterprise.misteye.io/threat-intelligence/SM-2026-378450)

Обзор цепочки атак

Технический анализ в этой статье основан исключительно на локальном оффлайн-статическом анализе, включающем распаковку, декодирование и проверку на деобфускацию трех образцов npm tgz.

Образцы, охватываемые данной проверкой, следующие:

@redhat-cloud-services/frontend-components-config

Версия: 6.11.3

tgz SHA-256: 0c9c67ec40d5f23efa1ec3470d0ac88b4993ccc0e92be913fc29a337dfc4f060

@redhat-cloud-services/types

Версия: 3.6.1

tgz SHA-256: d543bb3cdf1569c2b3d38c8a4081ed746cfe78bf3236c2302704d79ab7fa9558

@redhat-cloud-services/rule-components

Версия: 4.7.2

tgz SHA-256: aaf00d06baa3c679b82452c50014e9824b8874e9ca2d150f19095f8de19ba90f

Три образца имеют одинаковый вектор атаки: в каждом файле package.json присутствует scripts.preinstall = "node index.js". Это означает, что при установке этих версий на хосте разработчика или в среде CI/CD файл index.js в корневой директории будет автоматически выполнен на этапе установки, без необходимости явного импорта или запуска бизнес-кода пользователем.

Три образца используют общий основной вредоносный payload, но различаются параметрами внешней обертки. То есть, три образца применяют разные значения сдвига ROT/Caesar и разные ключи/AES-GCM IV/теги; это затрудняет прямое повторное использование статических признаков, основанных на хеше внешней обертки, фиксированном ключе или фиксированном сдвиге. Однако хеши расшифрованного загрузчика среды выполнения Bun и основного вредоносного payload полностью совпадают: один — это вспомогательный модуль для подготовки среды выполнения Bun, другой — настоящий основной payload, содержащий вредоносные функции. В данной статье они называются соответственно «загрузчик среды выполнения Bun» (имя переменной в исходном коде _b) и «основной вредоносный payload» (имя переменной в исходном коде _p).

Восстановленная цепочка атаки выглядит следующим образом:

Технический анализ

1. Вход: подмена сценариев жизненного цикла npm

Все три образца запускают цепочку атак через жизненный цикл preinstall в package.json:

"scripts": {

"preinstall": "node index.js"

}

preinstall будет автоматически выполнен на этапе установки npm. Для обычных фронтенд-компонентов, типов или пакетов правил запуск крупного JavaScript-файла в корневой директории на этапе установки обычно не требуется; это самый прямой сигнал аномалии.

Следующие доказательства на уровне образца:

@redhat-cloud-services/frontend-components-config@6.11.3

  • main: lib/index.js
  • Поле files: ["/lib", "/bin"]
  • Корневой каталог index.js SHA-256: 545a1838c66e1771f58d84a17b3e1841e5eeab91a73f4ccc59c9492450a6d9c0

@redhat-cloud-services/types@3.6.1

  • main: index.d.ts
  • Поле files: не установлено
  • Корневой каталог index.js SHA-256: b86c5ae9e95bd841a595440faa3eb6317441e746f241ae8fd641ab59ed1d1966

@redhat-cloud-services/rule-components@4.7.2

  • main: index.js
  • Поле files: не установлено
  • Корневой каталог index.js SHA-256: 1a30a9abe20bab121aaa75ed040565af14e6cdfb745609ee0e7b94a2d814fb9c

В частности, поле files в frontend-components-config@6.11.3 объявляет только "/lib" и "/bin", но в корне tarball существует дополнительный файл index.js, вызываемый в preinstall. Эта аномалия применима только к этому образцу; types@3.6.1 и rule-components@4.7.2 не задают поле files, поэтому эту аномалию нельзя обобщать на все образцы.

2. Первый уровень: массив чисел + ROT/Caesar замена букв

Корневой файл index.js всех трёх образцов — это огромный однострочный JavaScript-файл с одинаковой структурой, основой которого является обёртка try { eval(...) } catch (...)

Этот обертка сначала восстанавливает огромный массив чисел в строку с помощью String.fromCharCode, затем выполняет ROT/Caesar-сдвиг для английских букв в строке и передает результат декодирования в eval для выполнения. Обработка исключений выводит только префикс wrapper:, чтобы снизить заметность исключений при неудачной установке.

Значения внешнего смещения и хэш Stage 2 для трех образцов следующие:

frontend-components-config@6.11.3

index.js размер: 4 294 798 байт

ROT/Caesar shift: 10

Этап 2 SHA-256: b19c2fd48535c8c40aeb3e627ce92775f33ef9292611767bb1236c238e6f90cc

types@3.6.1

index.js размер: 4 135 588 байт

ROT/Caesar shift: 4

Этап 2 SHA-256: 9c0425aa6e6d7792ac38d24f3e7245f42fcaa553ddfeb6bd97677017f10c3b75

rule-components@4.7.2

index.js размер: 4 294 336 байт

ROT/Caesar shift: 11

Этап 2 SHA-256: d590bd375d95e4ac072b7ebc1fc4489bcaf5f20a939e92486267aa398bcf1e5d

3. Второй уровень: AES-128-GCM расшифровка Bun-загрузчика и основного полезного груза

Код этапа 2, расшифрованный с помощью ROT/Caesar, выполняет AES-128-GCM (Advanced Encryption Standard - Galois/Counter Mode) расшифровку с использованием Node.js crypto.createDecipheriv и устанавливает маркер аутентичности с помощью setAuthTag. Целью расшифровки являются два последующих компонента — загрузчик среды выполнения Bun и основной вредоносный код.

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

Три образца были зашифрованы с использованием разных ключей AES-128-GCM, начальных векторов и маркеров аутентификации для обоих компонентов, однако после расшифровки SHA-256 трех Bun-окружений для загрузки составляет ac2a2208e1726e008be6c73dc0872d9bba163319259dff1b62055ac933ca46b6, а SHA-256 трех основных вредоносных нагрузок — 0dc06ecdaa63fe24859cfd955053c23245c536e4733480239d14bebf12688e35. Это указывает на то, что злоумышленники изменили параметры внешней обертки в разных npm-пакетах, но повторно использовали одну и ту же основную вредоносную компоненту.

После расшифровки Stage 2 записывает основной вредоносный нагрузку в /tmp, выполняет её через Bun, а затем удаляет временный файл. Реальная логика, восстановленная из трёх образцов, выглядит следующим образом:

Таким образом, проверяемый шаблон временных файлов в трех образцах:

/tmp/p.js

Размер загрузчика среды выполнения Bun составляет 898 байт, хеши трех образцов полностью совпадают:

ac2a2208e1726e008be6c73dc0872d9bba163319259dff1b62055ac933ca46b6

Bun-среда выполнения загрузчика содержит логику, такую как child_process.execSync, fs.existsSync, fs.mkdtempSync, fs.chmodSync, os.platform(), os.arch(), getBunPath(), для поиска или подготовки среды выполнения Bun. То есть Stage 2 не предполагает просто, что глобальный Bun уже установлен в системе; в путях, отличных от среды выполнения Bun, он сначала загружает загрузчик среды выполнения Bun, а затем вызывает Bun через getBunPath() для выполнения основной вредоносной нагрузки.

4. Третий уровень: строковая таблица obfuscator.io

Основный вредоносный payload, извлеченный из шифрования, не является читаемым открытым JavaScript-кодом, а дополнительно запутан с использованием стиля obfuscator.io — строковые таблицы. Этот слой концентрирует множество строк в массивах и восстанавливает их во время выполнения с помощью индексации и логики вращения, что препятствует аналитикам в получении доступа к ключевым API, путям и именам конфигураций до полного восстановления строковой таблицы.

5. Четвертый уровень: B5 пользовательское шифрование строк

После восстановления таблицы строк obfuscator.io в ядре вредоносной нагрузки сохраняется еще один уровень пользовательского шифрования строк B5. Параметры подтверждены:

  • KDF: PBKDF2 (Password-Based Key Derivation Function 2)
  • Хэш-функция: SHA-256
  • Количество итераций: 200000
  • Длина ключа: 32 байта
  • Количество раундов дешифрования: 3
  • пароль: ba2c6ddb3672bdd6a611e6850b4f700b52aed3dab2f1b3d5f8c839d4a157a709
  • salt: 5b26508dc0f1075a7c0b4d8aa464487e

Расшифрованный результат следующий:

В частности, после расшифровки B5 становятся видны различные ключевые открытые строки. Следует отметить, что некоторые строки изначально находились в таблице строк obfuscator.io и становятся непосредственно доступными для grep только после завершения обоих шагов: «замена таблицы строк + расшифровка B5»:

6. Дополнительный встраиваемый слой: AES-256-GCM + gzip

Внутри основного вредоносного груза содержатся встроенные ресурсы, зашифрованные с использованием AES-256-GCM и сжатые с помощью gzip. Логика восстановления использует:

Ключевые встроенные ресурсы, которые были расшифрованы, разделены на три категории по функциям:

Чтение памяти через платформы:

Эти ресурсы используются для чтения памяти работающих процессов. Ключи и токены в обычных файлах можно обнаружить путем поиска файлов, но CI/CD Runner или инструменты разработки временно сохраняют некоторые конфиденциальные значения в памяти во время выполнения. Злоумышленники внедряют скрипты для чтения памяти на трех платформах — Linux, Windows и macOS — с целью извлечь эти временные секреты из памяти процессов на различных системах.

Постоянная конфигурация:

Эти ресурсы используются для «оставления точек триггера для обратного доступа». То есть, даже после завершения первоначального процесса установки npm, злоумышленники хотят, чтобы вредоносный код снова запускался, когда разработчик в дальнейшем открывает проект, запускает редактор, входит в сессию Claude Code или система снова входить в систему. Поэтому эти ресурсы нацелены на конфигурацию на уровне проекта и на механизмы автозапуска на уровне пользователя: конфигурация на уровне проекта более скрытна, а системные службы лучше подходят для длительной работы.

C2 и распространение:

Эти встроенные ресурсы используются для последующего управления цепочками и переноса секретов репозитория. После расшифровки YZ представляет собой монитор поиска коммитов GitHub, который периодически ищет коммит-сообщения в формате firedalazer ., проверяет подпись, а затем загружает и выполняет удалённый Python-контент; zZ после расшифровки представляет собой шаблон рабочего процесса GitHub Actions под названием Run Copilot, который записывает ${{ toJSON(secrets) }} в файл format-results.txt и загружает его в качестве артефакта. Первый обеспечивает цепочку получения/выполнения последующих задач, второй предоставляет шаблон для переноса секретов репозитория через артефакты GitHub Actions; фактическая инъекция рабочего процесса, ожидание выполнения и загрузка артефактов осуществляются с помощью сопутствующей логики GitHub API, встроенной в основной нагрузочный код.

Анализ основных возможностей вредоносной нагрузки

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

Чтение памяти GitHub Actions Runner:

Образ содержит скрипты для чтения памяти на платформах Linux, Windows и macOS, обеспечивающие кроссплатформенную возможность дампа. Реализация для Linux выполняет извлечение памяти путем чтения файлов /proc//maps и /proc//mem целевого процесса:

Активная логика запуска вредоносной нагрузки нацелена на Linux-раннер GitHub Actions: когда GITHUB_ACTIONS === "true" и RUNNER_OS === "Linux", код ищет процесс Runner.Worker, делает дамп памяти, а затем извлекает маскированные секреты в формате "":{"value":"","isSecret":true}. В трех образцах подтвержденные пути активного сбора сосредоточены на Linux-раннере, однако сценарии для всех трех платформ уже встроены.

2. Мультиоблако и сбор локальных учетных данных разработчика:

Основный вредоносный нагрузка включает систематизированный модуль сбора учетных данных, охватывающий облачные провайдеры, среды CI, локальные настройки разработчиков, GitHub CLI, менеджеры паролей и файлы кошельков.

Цели сбора учетных данных облачного провайдера:

Модуль AWS также содержит логику, связанную с ECS/IMDS (Instance Metadata Service)/STS WebIdentity.

Сбор локальных учетных данных разработчика охватывает следующие цели:

Логика менеджера паролей реализована в исходном коде в виде массива runCommand(command, args), а не через конкатенацию строк оболочки.

Модуль сбора учетных данных охватывает широкий спектр целей — от облачных платформ до локальных устройств разработчиков; собранные конфиденциальные данные передаются с помощью следующих механизмов.

3. Внешний доступ к GitHub API и dead-drop:

Основный вредоносный нагрузка использует GitHub API в качестве основного канала для экспорта данных. Запросы маскируются под User-Agent python-requests/2.31.0; после проверки токена с помощью x-oauth-scopes (должен содержать repo, public_repo или workflow) выполняется экспортирующая операция: создается репозиторий (описание фиксировано как Miasma: The Spreading Blight), а похищенные данные, закодированные в base64, записываются через PUT /repos///contents/results/.

Кроме того, нагрузка реализует механизм dead-drop на основе поиска коммитов GitHub, получая команды C2 через поиск маркера "thebeautifulmarchoftime" (или "thebeautifulsnadsoftime"):

let result = await X9("thebeautifulmarchoftime ", xZ);

Встроенный ресурс YZ.bin представляет собой независимый монитор коммитов GitHub, который с интервалом 3600 секунд опрашивает поиск коммит-сообщений в формате firedalazer . После успешной проверки цифровой подписи загружает и выполняет удалённый Python-контент. Это формирует отдельную цепочку последующего управления, независимую от основного канала экстравагантной передачи.

В исходном коде также содержится конфигурационный блок HTTP POST-отправителя, нацеленный на конечные точки api.anthropic.com и v1/api. Поле noop этого конфигурационного блока установлено в значение true, что означает, что при отсутствии внешних изменений этот отправитель не будет инициировать реальные сетевые запросы. Следовательно, статический анализ может подтвердить только наличие данной структуры кода, но не доказывает наличие активного экспорта данных в Anthropic API.

4. Заражение репозитория GitHub и рабочего процесса:

Основный вредоносный груз может выполнять операции с git-объектами репозитория через GitHub REST / GraphQL API:

Вредоносный рабочий процесс, сконструированный под видом релиза, запрашивает разрешение id-token: write и использует путь OIDC (OpenID Connect) для получения токена публикации npm. Переменные среды и интерфейс пути OIDC: ACTIONS_ID_TOKEN_REQUEST_TOKEN, ACTIONS_ID_TOKEN_REQUEST_URL, аудитория установлена как npm:registry.npmjs.org. На уровне исходного кода подтверждается, что полезная нагрузка способна внедрять рабочие процессы в репозиторий GitHub и использовать OIDC / надежную публикацию npm для получения прав на публикацию.

Помимо вышеупомянутого способа инъекции рабочего процесса через git refs, нагрузка также включает более скрытый механизм переноса секретов: рабочий процесс GitHub Actions, маскирующийся под Run Copilot, записывает ${{ toJSON(secrets) }} в файл format-results.txt и загружает артефакт. В отличие от прямой записи секретов в содержимое репозитория, этот подход ориентирован на перенос данных через результаты выполнения рабочего процесса, и обычный код-ревью может не показать окончательное содержимое экспортированных секретов.

5. Запустите рабочий процесс Copilot через artifact для переноса secrets:

Встроенный ресурс zZ.bin представляет собой GitHub Actions-рабочий процесс, маскирующийся под Copilot, который записывает ${{ toJSON(secrets) }} в format-results.txt и загружает его в качестве артефакта.

Сопутствующее поведение GitHub API включает: создание/обновление временной ветки → запись blob рабочего процесса → ожидание выполнения рабочего процесса → загрузка артефакта в формате zip → чтение format-results.txt → удаление выполнения рабочего процесса и временной ветки. Соответствующие ключевые слова для поиска: Run Copilot, VARIABLE_STORE, format-results, chore/add-codeql-static-analysis, .github/workflows/codeql.yml.

6. npm самораспространение:

Основный вредоносный нагрузка имеет две независимые пути публикации / распространения через npm.

Путь токена npm: загрузка через GET /-/npm/v1/tokens перечисляет токены npm текущего пользователя, фильтрует токены с bypass_2fa === true и правами на запись в пакет, используя эти токены для автоматической публикации. bypass_2fa — это поле метаданных токена, а не параметр тела публикации.

Путь GitHub Actions OIDC: считывает переменные окружения ACTIONS_ID_TOKEN_REQUEST_TOKEN и ACTIONS_ID_TOKEN_REQUEST_URL, запрашивает OIDC-токен с аудиторией npm:registry.npmjs.org и обменивает его через интерфейс обмена OIDC-токенами npm для получения прав на публикацию.

Процесс заражения tarball-файла: распаковка → запись вредоносного index.js → изменение package.json:

Здесь различаются два типа входных точек: для трех локально загруженных образцов используется preinstall: "node index.js" — в этом случае среда установки не требует предварительной установки Bun, и использование Node.js в качестве начальной точки более скрытно; при самораспространении и заражении других пакетов записывается preinstall: "bun run index.js" и добавляется зависимость от bun — поскольку последующая логика основного вредоносного груза зависит от API, предоставляемого средой выполнения Bun (такими как Bun.gunzipSync и Bun.file), в сценарии самораспространения необходимо обеспечить наличие Bun в целевой среде.

7. Механизм постоянного хранения:

Основный вредоносный нагрузка содержит четыре метода постоянства, охватывающие каталог проекта и автозагрузку на уровне системы.

Claude Code SessionStart hook: Внедрение ресурса S8.bin записывает SessionStart hook в .claude/settings.json, автоматически запуская node .claude/setup.mjs при каждом запуске сессии Claude Code. Зловредная нагрузка также записывается в .claude/setup.mjs и .claude/index.js (путь формируется как ".claude/" + M0, где M0 = "index.js").

Задача folderOpen в VS Code: встроенный ресурс EZ.bin записывает задачу folderOpen в файл .vscode/tasks.json и автоматически запускает тот же скрипт при открытии папки зараженного проекта. Также записывается файл .vscode/setup.mjs.

kitty-monitor (systemd / LaunchAgent): встраивает ресурс RZ.bin для установки постоянной службы; файлы расположены в /.local/share/kitty/cat.py, /.config/systemd/user/kitty-monitor.service (Linux) и ~/Library/LaunchAgents/com.user.kitty-monitor.plist (macOS). Вредоносная нагрузка создает каталог /tmp/kitty-, записывает YZ.bin (монитор коммитов GitHub) в cat.py, а затем устанавливает его через RZ.bin.

gh-token-monitor (systemd / LaunchAgent): встраивает ресурс jZ.bin для установки службы мониторинга GitHub-токена; файлы расположены в каталогах /.local/bin/gh-token-monitor.sh и /.config/gh-token-monitor/, а также в соответствующих путях systemd / LaunchAgent. Монитор проверяет, возвращает ли GitHub-токен код состояния 40x, и является ли метаданные npm-пакета @cap-js/openapi@1.4.1 аномальными; при срабатывании выполняется обработчик:

Это означает, что при обнаружении monitor, что GitHub API возвращает код состояния 40x, например, при отозвании, истечении срока действия или необычном состоянии разрешений вредоносный скрипт выполняет переданный обработчик. Восстановленные обработчики из трех образцов в этой статье: rm -rf ~/; rm -rf ~/Documents. При реагировании нельзя непосредственно отзывать токен на хосте, где payload, возможно, все еще выполняется — сначала необходимо изолировать хост, удалить механизмы постоянного внедрения и запущенные процессы, а затем изменить учетные данные из чистой среды.

8. Harden-Runner / StepSecurity:

Основный вредоносный нагрузка содержит встроенные механизмы обнаружения и разрушения StepSecurity Harden-Runner, обходя защиту CI/CD следующим образом:

  1. Проверить доступность Docker-сокета /var/run/docker.sock;
  2. Перечислите контейнеры Docker, соответствующие ключевым словам harden-runner / stepsecurity в имени или образе;
  3. Завершите совпадающий контейнер с помощью POST /containers//kill;
  4. Создайте привилегированный контейнер Alpine и замените файл sudoers на runner ALL=(ALL) NOPASSWD:ALL;
  5. Запишите недопустимые записи для доменов StepSecurity в файл /etc/hosts;
  6. Перезапишите /etc/resolv.conf как 8.8.8.8 и 1.1.1.1.

Эта адаптация логики указывает, что образ специально настроен для сред CI/CD, защищенных StepSecurity.

9. EDR / Обнаружение безопасных продуктов, оценка среды и обход:

Основный вредоносный нагрузка обнаруживает имена процессов и пути установки различных продуктов EDR (Endpoint Detection and Response) / безопасности:

Полезная нагрузка также содержит логику обхода регионов: обнаруживаются переменные окружения LC_ALL, LC_MESSAGES, LANGUAGE, LANG; если после приведения к нижнему регистру они начинаются с ru, выполнение пропускается. Поддерживается распознавание сред CI, включая GitHub Actions, GitLab CI, Travis CI, CircleCI, Jenkins, AWS CodeBuild, Buildkite, AppVeyor, Bitbucket, Drone, TeamCity, Cirrus CI и др. Метки состояния, используемые во время выполнения: tmp.0987654321.lock, __IS_DAEMON (метка для дочернего процесса detached daemon), SKIP_DOMAIN (пропустить путь domain sender), /tmp/kitty-*, cat.py и /var/tmp/.gh_update_state.

Анализ влияния

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

На уровне хоста разработчика. Образцы собирают переменные среды, .npmrc, .pypirc, SSH-ключи, конфигурацию Docker, .env, токен GitHub CLI, данные менеджера паролей и файлы кошельков, а также обеспечивают дальнейшую возможность триггера через Claude Code, VS Code, systemd user service или macOS LaunchAgent.

На уровне CI/CD Runner. Образец распознает Linux-раннер GitHub Actions, считывает память процесса Runner.Worker и извлекает маскированные секреты; также содержит противодействующую логику StepSecurity Harden-Runner, стремящуюся нарушить или обойти компоненты защиты CI/CD.

На уровне организации и репозитория GitHub. Образец может создавать репозитории с помощью GitHub API, записывать данные в contents/results/, управлять git refs/blobs/trees/commits, внедрять вредоносный workflow и переносить секреты с помощью Run Copilot workflow + artifact.

На уровне распространения экосистемы npm. Можно отобрать токены npm, обладающие правами записи в пакет и с параметром bypass_2fa === true, либо использовать путь GitHub Actions OIDC / надежная публикация npm для получения прав на публикацию; затем загрузить целевой tarball, вставить вредоносный загрузчик, изменить preinstall, добавить зависимость от Bun, повысить версию patch и опубликовать, создав таким образом цепочку самораспространения в npm.

Сводка

Доказательства исходного кода трех образцов показывают, что данный вредоносный пакет представляет собой не просто скрипт кражи данных на этапе установки, а комбинацию многоэтапного загрузчика и полнофункционального импланта: внешний слой случайным образом изменяется в зависимости от пакета, а среда выполнения Bun и основной вредоносный нагрузка остаются неизменными; основной имплант охватывает такие этапы, как сбор учетных данных, извлечение CI-секретов, распространение через GitHub/npm, постоянное присутствие и противодействие защитным механизмам.

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

Многоуровневая цепочка деобфускации. Вредоносная нагрузка проходит через пять уровней упаковки: числовые массивы + ROT-замена букв, шифрование AES-128-GCM, обфускация через obfuscator.io, собственная строковая шифровка B5, а также вложенная прослойка AES-256-GCM + gzip. Ключи или параметры каждого уровня могут независимо изменяться в разных пакетах, что затрудняет массовое обнаружение на основе статических признаков.

Полные организационные возможности атаки. Этот имплант обладает способностями к чтению памяти GitHub Actions Runner, сбору учетных данных в многоклаудной и локальной средах, экспорту через GitHub API и dead-drop, заражению репозиториев и рабочих процессов GitHub, самораспространению через npm, обеспечению постоянства и противодействию защитным механизмам. Согласно структуре исходного кода, он уже содержит кодовые пути для распространения от единичной установки до репозиториев, CI/CD и цепочек публикации npm; реальный масштаб распространения необходимо подтвердить с помощью журналов установки, аудита репозиториев и телеметрии платформы.

Из доказательств исходного кода можно подтвердить, что все три образца автоматически запускаются через preinstall и расшифровывают и выполняют один и тот же основной имплант. Однако получить первоначальный доступ в реальном инциденте нельзя доказать только на основе этих трех образцов tgz.

Рекомендации по обработке

  1. Выявите и удалите вредоносные версии из зависимостей проекта, файлов блокировок, кэша частных реестров и кэша сборки.
  2. Проверьте журнал установки на наличие preinstall, node index.js, bun run, /tmp/p*.js, tmp.0987654321.lock.
  3. Не отменяйте токен непосредственно на заражённом хосте, пока он всё ещё может выполнять payload. Рекомендуется сначала изолировать заражённый хост, очистить запущенные процессы и элементы постоянного доступа, а затем заменить токены, связанные с GitHub, npm, облачными учётными данными, Kubernetes, Vault, SSH, реестром Docker и менеджерами паролей, из чистой среды.
  4. Проверьте недавние ветки, коммиты, рабочие процессы, артефакты и новые репозитории на GitHub, уделяя особое внимание ключевым словам: Run Copilot, format-results, chore/add-codeql-static-analysis, .github/workflows/codeql.yml, OIDC_PACKAGES.
  5. Проверьте, были ли добавлены или изменены файлы в каталоге проекта: .claude/settings.json, .claude/setup.mjs, .vscode/tasks.json, .vscode/setup.mjs.
  6. Проверьте файлы пользовательской постоянной настройки: /.local/share/kitty/cat.py, /.config/systemd/user/kitty-monitor.service, ~/Library/LaunchAgents/com.user.kitty-monitor.plist, файлы, связанные с gh-token-monitor.
  7. Проверить историю публикаций npm, чтобы убедиться в отсутствии неавторизованных патч-версий; также провести аудит метаданных токенов npm, уделяя особое внимание токенам, которые могут обойти 2FA и имеют права на запись в пакет.
  8. Perform an integrity audit on downstream artifacts built in a contaminated environment.

IOC

Вредоносный файл

filename: redhat-cloud-services-frontend-components-config-6.11.3.tgz MD5: 633ad8849a59e2bfb7a0fe589e816a07 SHA1: 675294612f455fe6a9acb195f0cbe3687d8e2e34 SHA256: 0c9c67ec40d5f23efa1ec3470d0ac88b4993ccc0e92be913fc29a337dfc4f060

имя файла: redhat-cloud-services-types-3.6.1.tgz MD5: 9e6c5af01438b52c9a411686c1f1b8ff SHA1: 88d098c8d96e9ae17550e9798c3b62c420464b8c SHA256: d543bb3cdf1569c2b3d38c8a4081ed746cfe78bf3236c2302704d79ab7fa9558

имя файла: redhat-cloud-services-rule-components-4.7.2.tgz MD5: f1ffdbf5e639899f26a6ebab2eec408d SHA1: f3c5c21274045ae02fef11e931de6dcf8462a067 SHA256: aaf00d06baa3c679b82452c50014e9824b8874e9ca2d150f19095f8de19ba90f

SHA256

ac2a2208e1726e008be6c73dc0872d9bba163319259dff1b62055ac933ca46b6

0dc06ecdaa63fe24859cfd955053c23245c536e4733480239d14bebf12688e35

Злоупотребление зависимостью

npm:@redhat-cloud-services/topological-inventory-client@3.0.10

npm:@redhat-cloud-services/topological-inventory-client@3.0.11

npm:@redhat-cloud-services/topological-inventory-client@3.0.13

npm:@redhat-cloud-services/compliance-client@4.0.3

npm:@redhat-cloud-services/compliance-client@4.0.4

npm:@redhat-cloud-services/compliance-client@4.0.6

npm:@redhat-cloud-services/rbac-client@9.0.3

npm:@redhat-cloud-services/rbac-client@9.0.4

npm:@redhat-cloud-services/rbac-client@9.0.6

npm:@redhat-cloud-services/insights-client@4.0.4

npm:@redhat-cloud-services/insights-client@4.0.5

npm:@redhat-cloud-services/insights-client@4.0.7

npm:@redhat-cloud-services/frontend-components@7.7.2

npm:@redhat-cloud-services/frontend-components@7.7.3

npm:@redhat-cloud-services/frontend-components@7.7.5

npm:@redhat-cloud-services/frontend-components-utilities@7.4.1

npm:@redhat-cloud-services/frontend-components-utilities@7.4.2

npm:@redhat-cloud-services/frontend-components-utilities@7.4.4

npm:@redhat-cloud-services/remediations-client@4.0.4

npm:@redhat-cloud-services/remediations-client@4.0.5

npm:@redhat-cloud-services/remediations-client@4.0.7

npm:@redhat-cloud-services/frontend-components-notifications@6.9.2

npm:@redhat-cloud-services/frontend-components-notifications@6.9.3

npm:@redhat-cloud-services/frontend-components-notifications@6.9.5

npm:@redhat-cloud-services/patch-client@4.0.4

npm:@redhat-cloud-services/patch-client@4.0.5

npm:@redhat-cloud-services/patch-client@4.0.7

npm:@redhat-cloud-services/host-inventory-client@5.0.3

npm:@redhat-cloud-services/host-inventory-client@5.0.4

npm:@redhat-cloud-services/host-inventory-client@5.0.6

npm:@redhat-cloud-services/rule-components@4.7.2

npm:@redhat-cloud-services/rule-components@4.7.3

npm:@redhat-cloud-services/rule-components@4.7.5

npm:@redhat-cloud-services/frontend-components-advisor-components@3.8.2

npm:@redhat-cloud-services/frontend-components-advisor-components@3.8.4

npm:@redhat-cloud-services/frontend-components-advisor-components@3.8.6

npm:@redhat-cloud-services/notifications-client@6.1.4

npm:@redhat-cloud-services/notifications-client@6.1.5

npm:@redhat-cloud-services/notifications-client@6.1.7

npm:@redhat-cloud-services/sources-client@3.0.10

npm:@redhat-cloud-services/sources-client@3.0.11

npm:@redhat-cloud-services/sources-client@3.0.13

npm:@redhat-cloud-services/integrations-client@6.0.4

npm:@redhat-cloud-services/integrations-client@6.0.5

npm:@redhat-cloud-services/integrations-client@6.0.7

npm:@redhat-cloud-services/frontend-components-config@6.11.3

npm:@redhat-cloud-services/frontend-components-config@6.11.4

npm:@redhat-cloud-services/frontend-components-config@6.11.6

npm:@redhat-cloud-services/frontend-components-config-utilities@4.11.2

npm:@redhat-cloud-services/frontend-components-config-utilities@4.11.3

npm:@redhat-cloud-services/frontend-components-config-utilities@4.11.5

npm:@redhat-cloud-services/hcc-pf-mcp@0.6.1

npm:@redhat-cloud-services/hcc-pf-mcp@0.6.2

npm:@redhat-cloud-services/hcc-pf-mcp@0.6.4

npm:@redhat-cloud-services/frontend-components-remediations@4.9.2

npm:@redhat-cloud-services/frontend-components-remediations@4.9.3

npm:@redhat-cloud-services/frontend-components-remediations@4.9.5

npm:@redhat-cloud-services/eslint-config-redhat-cloud-services@3.2.1

npm:@redhat-cloud-services/eslint-config-redhat-cloud-services@3.2.2

npm:@redhat-cloud-services/eslint-config-redhat-cloud-services@3.2.4

npm:@redhat-cloud-services/javascript-clients-shared@2.0.8

npm:@redhat-cloud-services/javascript-clients-shared@2.0.9

npm:@redhat-cloud-services/javascript-clients-shared@2.0.11

npm:@redhat-cloud-services/quickstarts-client@4.0.11

npm:@redhat-cloud-services/quickstarts-client@4.0.12

npm:@redhat-cloud-services/quickstarts-client@4.0.14

npm:@redhat-cloud-services/config-manager-client@5.0.4

npm:@redhat-cloud-services/config-manager-client@5.0.5

npm:@redhat-cloud-services/config-manager-client@5.0.7

npm:@redhat-cloud-services/hcc-feo-mcp@0.3.1

npm:@redhat-cloud-services/hcc-feo-mcp@0.3.2

npm:@redhat-cloud-services/hcc-feo-mcp@0.3.4

npm:@redhat-cloud-services/entitlements-client@4.0.11

npm:@redhat-cloud-services/entitlements-client@4.0.12

npm:@redhat-cloud-services/entitlements-client@4.0.14

npm:@redhat-cloud-services/tsc-transform-imports@1.2.2

npm:@redhat-cloud-services/tsc-transform-imports@1.2.4

npm:@redhat-cloud-services/tsc-transform-imports@1.2.6

npm:@redhat-cloud-services/hcc-kessel-mcp@0.3.1

npm:@redhat-cloud-services/hcc-kessel-mcp@0.3.2

npm:@redhat-cloud-services/hcc-kessel-mcp@0.3.4

npm:@redhat-cloud-services/frontend-components-testing@1.2.1

npm:@redhat-cloud-services/frontend-components-testing@1.2.2

npm:@redhat-cloud-services/frontend-components-testing@1.2.4

npm:@redhat-cloud-services/types@3.6.1

npm:@redhat-cloud-services/types@3.6.2

npm:@redhat-cloud-services/types@3.6.4

npm:@redhat-cloud-services/chrome@2.3.1

npm:@redhat-cloud-services/chrome@2.3.2

npm:@redhat-cloud-services/chrome@2.3.4

npm:@redhat-cloud-services/frontend-components-translations@4.4.1

npm:@redhat-cloud-services/frontend-components-translations@4.4.2

npm:@redhat-cloud-services/frontend-components-translations@4.4.4

npm:@redhat-cloud-services/vulnerabilities-client@2.1.8

npm:@redhat-cloud-services/vulnerabilities-client@2.1.9

npm:@redhat-cloud-services/vulnerabilities-client@2.1.11

Отказ от ответственности: Информация на этой странице может быть получена от третьих лиц и не обязательно отражает взгляды или мнения KuCoin. Данный контент предоставляется исключительно в общих информационных целях, без каких-либо заверений или гарантий, а также не может быть истолкован как финансовый или инвестиционный совет. KuCoin не несет ответственности за ошибки или упущения, а также за любые результаты, полученные в результате использования этой информации. Инвестиции в цифровые активы могут быть рискованными. Пожалуйста, тщательно оценивайте риски, связанные с продуктом, и свою устойчивость к риску, исходя из собственных финансовых обстоятельств. Для получения более подробной информации, пожалуйста, ознакомьтесь с нашими Условиями использования и Уведомлением о риске.