Инциденты

Масштабное заражение npm: червь Shai-Hulud и нулевой пациент

Введение

Современный мир разработки целиком и полностью зависит от сторонних модулей. Безусловно, это ускоряет разработку, но, так как эти модули могут создаваться любым желающим, это создает обширную поверхность атаки для конечных пользователей. Неудивительно, что возникают модули с вредоносной функциональностью. Компрометация одного аккаунта мейнтейнера популярных модулей или одной популярной зависимости быстро превращается в атаку на цепочку поставок. Подобные случаи компрометации стали частым явлением и «трендовым» направлением у злоумышленников. За последний месяц произошло два крупных инцидента, подтверждающих интерес злоумышленников к созданию вредоносных модулей, зависимостей и отдельных пакетов. Мы уже рассказывали о недавней компрометации популярных npm-пакетов, а 16 сентября 2025 года стало известно о новой волне заражения npm-пакетов при помощи самораспространяющегося зловреда Shai-Hulud.

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

Технические детали

Вредоносный код червя запускается при установке зараженного пакета и публикует зараженные релизы во все пакеты, на которые у жертвы есть право обновления.

После установки зараженного пакета из реестра npm в системе жертвы запускается особая команда, которая выполняется автоматически. Она запускает вредоносный скрипт размером более 3 МБ под названием bundle.js, в котором содержится несколько легитимных рабочих модулей с открытым исходным кодом.

Среди ключевых модулей в bundle.js можно отметить следующие.

  • Библиотека для работы с облачными сервисами AWS.
  • Модуль GCP, который позволяет получать метаданные из среды Google Cloud Platform.
  • Функции для работы с TruffleHog. Это инструмент для сканирования различных источников данных, позволяющий находить конфиденциальную информацию (в частности, секреты).
  • Инструмент для работы с GitHub API.

Также в JavaScript-файле содержатся сетевые утилиты для передачи данных и основной модуль работы Shai-Hulud.

Вредоносная активность червя начинается со сбора информации об операционной системе жертвы и проверки на наличие npm-токена и токена аутентифицированного пользователя GitHub в среде окружения. Если действительный GitHub-токен не установлен, bundle.js завершит работу. Отличительная черта Shai-Hulud заключается в том, что большая часть его функциональности нацелена на работу в системах Linux и macOS: практически все вредоносные действия выполняются исключительно в этих системах, за исключением поиска секретов при помощи инструмента TruffleHog.

Эксфильтрация секретов

После прохождения проверок зловред получает информацию о текущем пользователе GitHub через вышеуказанный токен и запускает функцию extraction. Она создает временный исполняемый bash-скрипт по пути /tmp/processor.sh, а затем запускает его как отдельный процесс, передавая токен в качестве аргумента. Далее представлена функция extraction, в которой мы видоизменили строки и переименовали переменные для удобства чтения: исходный код был отформатирован в нечитаемом виде.

Приведенная к читаемому виду функция extraction

Приведенная к читаемому виду функция extraction

Запущенный bash-скрипт предназначен для работы с GitHub через API: он собирает секреты из репозитория жертвы нестандартным образом. Сначала скрипт проверяет наличие у токена прав на создание веток в репозиториях и работу с GitHub Actions и в случае их наличия получает список всех репозиториев за 2025 год, к которым у пользователя есть доступ. В каждом из них bash-скрипт создает новую ветку под названием shai-hulud, для которой загружается workflow-скрипт shai-hulud-workflow.yml — это конфигурационный файл для описания рабочих процессов в GitHub Actions. Подобные файлы представляют собой скрипты автоматизации, которые активируются в GitHub Actions каждый раз, когда в репозиторий вносятся какие-либо изменения. Workflow-файл Shai-Hulud активируется при каждом запуске команды push.

Конфигурация вредоносного workflow-файла

Конфигурация вредоносного workflow-файла

Этот файл собирает секреты из репозиториев жертвы и отправляет их на сервер злоумышленников. Перед отправкой конфиденциальные данные дважды кодируются с помощью Base64.

Такой нестандартный метод сбора данных фактически создан для однократного извлечения секретов из репозиториев пользователя, однако он создает опасность не только для жертв Shai-Hulud, но и для обычных исследователей. Если набрать в поиске на GitHub shai-hulud, можно обнаружить множество репозиториев, которые пострадали от Shai-Hulud.

Открытые репозитории на GitHub – жертвы Shai-Hulud

Открытые репозитории на GitHub – жертвы Shai-Hulud

Далее основной скрипт bundle.js запрашивает список всех организаций, относящихся к жертве, и для каждой из них выполняет функцию migration. Эта функция также запускает bash-скрипт, только в этом случае она сохраняет его по пути /tmp/migrate-repos.sh, передавая в качестве параметров название организации, имя пользователя и токен для дальнейшей вредоносной активности.

Bash-скрипт автоматизирует миграцию всех приватных и внутренних репозиториев из указанной GitHub-организации в учетную запись пользователя, делая их публичными. Скрипт также использует GitHub API для копирования содержимого приватных репозиториев в виде зеркальных копий.

По нашим предположениям, подобные действия нужны для дальнейшей автоматизированной кражи исходного кода из приватных репозиториев популярных сообществ и организаций. К примеру, под волну заражений попала известная компания CrowdStrike.

Саморепликация червя

После операций с GitHub жертвы основной скрипт bundle.js приступает к следующему важному этапу — саморепликации. Сначала скрипт получает список из 20 самых скачиваемых пакетов жертвы. Для этого он выполняет поисковый запрос, в который подставляет имя пользователя из ранее полученного токена npm:

Затем для каждого полученного пакета вызывается функция updatePackage. Сначала она пытается скачать tarball-версию пакета (архив в формате .tar). Если такая версия существует, создается временная директория под названием npm-update-{название_целевого_пакета}. В нее сохраняется tarball-версия пакета под названием package.tgz, которая затем распаковывается и модифицируется следующим образом.

  • В оригинальный пакет добавляется вредоносный bundle.js.
  • В файл package.json (используется в проектах на Node.js для управления зависимостями и метаданными проекта) добавляется постинсталляционная команда (postinstall), в которую прописывается выполнение вредоносного скрипта через node bundle.js.
  • Версия пакета увеличивается на 1.

Модифицированный пакет заново упаковывается и при помощи команды npm publish публикуется в npm как новая версия. После этого временная директория для пакета очищается.

Приведенная к читаемому виду функция updatePackage

Приведенная к читаемому виду функция updatePackage

Публикация на GitHub

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

Также для сканирования секретов используются модули для работы с AWS и Google Cloud Platform (GCP). Далее скрипт агрегирует полученные данные в один объект и создает репозиторий в профиле жертвы с одноименным названием Shai-Hulud, куда выгружает собранную информацию в виде файла data.json.

Ниже представлен список форматов данных, собираемых из системы жертвы и загружаемых на GitHub.

Особенности заражения

Характерной особенностью модифицированных пакетов является то, что в них содержится архив под названием package.tar. На это следует обратить внимание, поскольку обычно в пакетах находится архив с названием, повторяющим название пакета.

Проведя ряд исследований, мы смогли обнаружить первый пакет, с которого началось распространение Shai-Hulud, благодаря одному ключевому отличию. Как мы упоминали ранее, после заражения в файл package.json прописывается постинсталляционная команда на выполнение вредоносного скрипта node bundle.js, выполняющаяся сразу после установки скрипта. Однако в одном из зараженных пакетов мы обнаружили ту же команду в качестве прединсталляционной, то есть она выполнялась перед установкой. Этим пакетом оказался ngx-bootstrap версии 18.1.4. Мы полагаем, что именно он стал отправной точкой распространения данной инфекции. Эту гипотезу подтверждает и то, что название архива в первой инфицированной версии этого пакета отличалось от характерного для уже зараженных (package.tar).

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

Зараженные библиотеки и CrowdStrike

В результате быстро развивающегося распространения червя Shai-Hulud было затронуто множество популярных библиотек, которые используют многие организации и разработчики ежедневно. За последние дни Shai-Hulud заразил более 500 популярных пакетов, в число которых вошли библиотеки известной компании CrowdStrike.

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

  • @crowdstrike/commitlint версий 8.1.1, 8.1.2
  • @crowdstrike/falcon-shoelace версий 0.4.1, 0.4.2
  • @crowdstrike/foundry-js версий 0.19.1, 0.19.2
  • @crowdstrike/glide-core версий 0.34.2, 0.34.3
  • @crowdstrike/logscale-dashboard версий 1.205.1, 1.205.2
  • @crowdstrike/logscale-file-editor версий 1.205.1, 1.205.2
  • @crowdstrike/logscale-parser-edit версий 1.205.1, 1.205.2
  • @crowdstrike/logscale-search версий 1.205.1, 1.205.2
  • @crowdstrike/tailwind-toucan-base версий 5.0.1, 5.0.2

Однако внимание к распространяющейся угрозе привлекло заражение библиотеки @ctrl/tinycolor, которую еженедельно скачивают более двух миллионов пользователей.

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

Профилактика и защита

Для защиты от заражений подобного рода мы рекомендуем использовать специальное решение для мониторинга компонентов с открытым исходным кодом. «Лаборатория Касперского» поддерживает постоянный фид скомпрометированных пакетов и библиотек, который можно использовать для обеспечения безопасности цепочки поставок и защиты разработок от подобных угроз.

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

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

Продукты «Лаборатории Касперского» детектируют угрозу Shai-Hulud с вердиктом HEUR:Worm.Script.Shulud.gen.

В случае заражения Shai-Hulud, а также в качестве проактивного реагирования на распространяющуюся угрозу мы советуем принять следующие меры в системах и инфраструктурах.

  • Провести полное сканирование системы при помощи надежного защитного решения.
  • Провести аудит репозиториев GitHub:
    • проверить наличие репозиториев с названием shai-hulud;
    • проверить наличие нетривиальных или неизвестных веток, запросов на вытягивание и файлов;
    • провести аудит логов GitHub Actions на наличие строк, содержащих shai-hulud.
  • Перевыпустить токены npm и GitHub, ключи от облаков (в частности, AWS и Google Cloud Platform), а также выполнить ротацию остальных секретов.
  • Очистить кэш и провести инвентаризацию модулей npm: проверить наличие вредоносных и откатить версии до чистых.
  • Проверить наличие индикаторов компрометации (файлов в системе или сетевых признаков).

Индикаторы компрометации

Файлы:
bundle.js
shai-hulud-workflow.yml

Строки:
shai-hulud

Хэши:
C96FBBE010DD4C5BFB801780856EC228
78E701F42B76CCDE3F2678E548886860

Сетевые признаки:
https://webhook.site/bb8ca5f6-4175-45d2-b042-fc9ebb8170b7

Скомпрометированные пакеты:
@ahmedhfarag/ngx-perfect-scrollbar
@ahmedhfarag/ngx-virtual-scroller
@art-ws/common
@art-ws/config-eslint
@art-ws/config-ts
@art-ws/db-context
@art-ws/di
@art-ws/di-node
@art-ws/eslint
@art-ws/fastify-http-server
@art-ws/http-server
@art-ws/openapi
@art-ws/package-base
@art-ws/prettier
@art-ws/slf
@art-ws/ssl-info
@art-ws/web-app
@basic-ui-components-stc/basic-ui-components
@crowdstrike/commitlint
@crowdstrike/falcon-shoelace
@crowdstrike/foundry-js
@crowdstrike/glide-core
@crowdstrike/logscale-dashboard
@crowdstrike/logscale-file-editor
@crowdstrike/logscale-parser-edit
@crowdstrike/logscale-search
@crowdstrike/tailwind-toucan-base
@ctrl/deluge
@ctrl/golang-template
@ctrl/magnet-link
@ctrl/ngx-codemirror
@ctrl/ngx-csv
@ctrl/ngx-emoji-mart
@ctrl/ngx-rightclick
@ctrl/qbittorrent
@ctrl/react-adsense
@ctrl/shared-torrent
@ctrl/tinycolor
@ctrl/torrent-file
@ctrl/transmission
@ctrl/ts-base32
@nativescript-community/arraybuffers
@nativescript-community/gesturehandler
@nativescript-community/perms
@nativescript-community/sentry
@nativescript-community/sqlite
@nativescript-community/text
@nativescript-community/typeorm
@nativescript-community/ui-collectionview
@nativescript-community/ui-document-picker
@nativescript-community/ui-drawer
@nativescript-community/ui-image
@nativescript-community/ui-label
@nativescript-community/ui-material-bottom-navigation
@nativescript-community/ui-material-bottomsheet
@nativescript-community/ui-material-core
@nativescript-community/ui-material-core-tabs
@nativescript-community/ui-material-ripple
@nativescript-community/ui-material-tabs
@nativescript-community/ui-pager
@nativescript-community/ui-pulltorefresh
@nstudio/angular
@nstudio/focus
@nstudio/nativescript-checkbox
@nstudio/nativescript-loading-indicator
@nstudio/ui-collectionview
@nstudio/web
@nstudio/web-angular
@nstudio/xplat
@nstudio/xplat-utils
@operato/board
@operato/data-grist
@operato/graphql
@operato/headroom
@operato/help
@operato/i18n
@operato/input
@operato/layout
@operato/popup
@operato/pull-to-refresh
@operato/shell
@operato/styles
@operato/utils
@teselagen/bio-parsers
@teselagen/bounce-loader
@teselagen/file-utils
@teselagen/liquibase-tools
@teselagen/ove
@teselagen/range-utils
@teselagen/react-list
@teselagen/react-table
@teselagen/sequence-utils
@teselagen/ui
@thangved/callback-window
@things-factory/attachment-base
@things-factory/auth-base
@things-factory/email-base
@things-factory/env
@things-factory/integration-base
@things-factory/integration-marketplace
@things-factory/shell
@tnf-dev/api
@tnf-dev/core
@tnf-dev/js
@tnf-dev/mui
@tnf-dev/react
@ui-ux-gang/devextreme-angular-rpk
@ui-ux-gang/devextreme-rpk
@yoobic/design-system
@yoobic/jpeg-camera-es6
@yoobic/yobi
ace-colorpicker-rpk
airchief
airpilot
angulartics2
another-shai
browser-webdriver-downloader
capacitor-notificationhandler
capacitor-plugin-healthapp
capacitor-plugin-ihealth
capacitor-plugin-vonage
capacitorandroidpermissions
config-cordova
cordova-plugin-voxeet2
cordova-voxeet
create-hest-app
db-evo
devextreme-angular-rpk
devextreme-rpk
ember-browser-services
ember-headless-form
ember-headless-form-yup
ember-headless-table
ember-url-hash-polyfill
ember-velcro
encounter-playground
eslint-config-crowdstrike
eslint-config-crowdstrike-node
eslint-config-teselagen
globalize-rpk
graphql-sequelize-teselagen
json-rules-engine-simplified
jumpgate
koa2-swagger-ui
mcfly-semantic-release
mcp-knowledge-base
mcp-knowledge-graph
mobioffice-cli
monorepo-next
mstate-angular
mstate-cli
mstate-dev-react
mstate-react
ng-imports-checker
ng2-file-upload
ngx-bootstrap
ngx-color
ngx-toastr
ngx-trend
ngx-ws
oradm-to-gql
oradm-to-sqlz
ove-auto-annotate
pm2-gelf-json
printjs-rpk
react-complaint-image
react-jsonschema-form-conditionals
react-jsonschema-form-extras
react-jsonschema-rxnt-extras
remark-preset-lint-crowdstrike
rxnt-authentication
rxnt-healthchecks-nestjs
rxnt-kue
swc-plugin-component-annotate
tbssnch
teselagen-interval-tree
tg-client-query-builder
tg-redbird
tg-seq-gen
thangved-react-grid
ts-gaussian
ts-imports
tvi-cli
ve-bamreader
ve-editor
verror-extra
voip-callkit
wdio-web-reporter
yargs-help-output
yoo-styles

Масштабное заражение npm: червь Shai-Hulud и нулевой пациент

Ваш e-mail не будет опубликован. Обязательные поля помечены *

 

Отчеты

ToddyCat — ваш скрытый почтовый ассистент. Часть 1

Эксперты «Лаборатории Касперского» разбирают атаки APT ToddyCat через корпоративную электронную почту. Изучаем новую версию TomBerBil, инструменты TCSectorCopy и XstReader, а также способы кражи токенов доступа из Outlook.

Криптоафера группы BlueNoroff: «призрачные» инвестиции и фиктивные рабочие предложения

Эксперты команды GReAT проанализировали кампании GhostCall и GhostHire APT-группы BlueNoroff: несколько цепочек вредоносного ПО для macOS, поддельные клиенты Zoom и Microsoft Teams, а также изображения, улучшенные с помощью ChatGPT.

Mem3nt0 mori – Hacking Team снова с нами!

Исследователи «Лаборатории Касперского» впервые обнаружили шпионское ПО Dante, разработанное Memento Labs (бывшей Hacking Team) в дикой природе и нашли его связь с APT ForumTroll.