31 марта 2026 года один украденный npm-токен превратил axios - HTTP-клиент с ~100 миллионами загрузок в неделю и 174 000 зависимых пакетов - в платформу доставки кроссплатформенного RAT. Huntress зафиксировал первое заражение на мониторимом хосте через 89 секунд после публикации вредоносной версии. 89 секунд. За три часа до отзыва пакета минимум 135 эндпоинтов уже стучались на C2-инфраструктуру атакующих - Windows, macOS, Linux. Google Threat Intelligence Group атрибутировал инцидент группе UNC1069 (КНДР). ThreatBook подтвердил связь с Lazarus через совпадение артефактов с трояном WAVESHAPER, который Mandiant задокументировал в феврале 2026.
Axios - не разовый случай. Sonatype (цитируется в отчёте shattered.io) насчитал в 2025 году более 454 600 новых вредоносных open-source пакетов, а кумулятивное число заблокированных перевалило за 1,2 миллиона - рост 75% год к году. Атаки на цепочку поставок ПО давно перестали быть эпизодами. Это индустриализированный канал initial access, который государственные акторы эксплуатируют наравне с фишингом и zero-day.
Бизнес-логика: почему КНДР атакует цепочку поставок ПО
Supply chain compromise для Lazarus - мультипликатор. Компрометация одного мейнтейнера дешевле и тише, чем сожжение zero-day, зато даёт доступ ко всем downstream-потребителям пакета. В случае axios - к 174 000+ зависимых проектов. В случае пакетов под scope @redhat-cloud-services (32 пакета, скомпрометированных 1 июня 2026 года, по данным Unit 42) - к корпоративным средам на Red Hat. Подробнее - в нашем подробном разборе атаки на цепочку поставок.Финансовая мотивация - ядро операций КНДР. AhnLab (цитируется itsec.ru) приписывает Lazarus Group хищения свыше $1,4 млрд только в криптосекторе за последние годы, включая кражу $1,4 млрд у биржи Bybit в феврале 2025. Supply chain атаки через npm прицельно бьют в разработчиков крипто- и Web3-проектов: именно на их рабочих станциях лежат приватные ключи кошельков, токены доступа к CI/CD и cloud credentials. Параллельно Lazarus ведёт кампании вроде Operation Marstech Mayhem (терминология SecurityScorecard) - поддельные GitHub-репозитории и npm-пакеты с обфусцированным JavaScript-имплантом, нацеленные на разработчиков.
По IBM X-Force Threat Intelligence Index 2025, атаки с использованием действительных учётных данных выросли на 71% год к году. Украденный npm-токен - по сути «действительные credentials» для registry. Supply chain compromise - одна из причин этого роста.
Kill chain supply chain атаки на npm
Полная цепочка от initial access до импакта:- Компрометация publishing identity - кража npm-токена или GitHub PAT (T1195.001, Initial Access)
- Публикация вредоносной версии пакета в registry (T1195.002, Initial Access)
- Автоматическое выполнение через postinstall hooks или import-time код (T1204.005 - Malicious Library, Execution)
- Загрузка Stage-2 payload с C2 или из IPFS (T1105 - Ingress Tool Transfer, Command and Control)
- Кража credentials, npm/GitHub токенов, крипто-кошельков
- Самораспространение через украденные токены - в worm-вариантах цикл замыкается на шаг 1
Axios: анатомия компрометации пакета с 100 млн загрузок
Инцидент с axios - наиболее документированная supply chain атака 2026 года. Разберём каждый этап.Захват publishing identity и обход OIDC
Атакующий получил доступ к npm-аккаунту jasonsaayman - основного мейнтейнера axios. По данным Huntress, email аккаунта сменили на ifstap@proton[.]me, заблокировав легитимному владельцу путь recovery. Сам мейнтейнер позже написал в GitHub issue #10604: «im trying to get support to understand how this even happened. i have 2fa / mfa on practically everything». Точный метод компрометации токена не установлен.А вот дальше - интересный момент, который зафиксировали Huntress и Picus Security. На ветке v1.x был настроен OIDC Trusted Publishing через GitHub Actions, но publish workflow всё равно передавал NPM_TOKEN как environment variable рядом с OIDC-credentials. Когда npm получает оба варианта аутентификации одновременно, он использует token. Результат: long-lived classic token де-факто оставался единственным механизмом аутентификации, а OIDC превращался в декорацию.
Для аудита CI/CD это критически важно: наличие OIDC Trusted Publishing не гарантирует защиту, если в pipeline одновременно передаётся classic token. Проверьте свои GitHub Actions workflows прямо сейчас - ищите строки с NPM_TOKEN в env-секции.
Атака была подготовлена за 18 часов до детонации:
- T-18h (30 марта, 05:57 UTC): публикация clean-версии plain-crypto-js@4.2.0 под аккаунтом nrwise (email: nrwise@proton[.]me). Цель - создать publishing history и закешировать имя пакета на npm-зеркалах и CDN
- T-0 (31 марта, ~00:00 UTC): публикация plain-crypto-js@4.2.1 с вредоносным postinstall hook, затем axios@1.14.1 (tagged latest) и axios@0.30.4 (tagged legacy). Единственное изменение в axios - одна строка в dependencies файла package.json, указывающая на plain-crypto-js. Ни один исходный файл, тест или логика не модифицированы
- T+89 секунд: первое заражение на мониторимом хосте - CI/CD пайплайны с caret ranges (^1.x) без pinned lockfile подтянули вредоносную версию при очередном
npm install - T+~3 часа: вредоносные версии отозваны npm security team
Кроссплатформенный RAT: от дроппера до anti-forensics
При установке plain-crypto-js@4.2.1 postinstall hook запускалnode setup.js - JavaScript-дроппер на 4 209 байт с двухслойной обфускацией (T1027 - Obfuscated Files or Information): reversed Base64 и XOR-шифр с ключом OrDeR_7077. Тут забавная деталь: буквенные символы ключа дают NaN при Number(), превращаются в 0 при побитовых операциях - эффективные цифры ключа: [0,0,0,0,0,0,7,0,7,7]. Все 18 обфусцированных строк в массиве stq[] скрывали имена модулей (child_process, os, fs), C2 URL, shell-команды и пути файлов.Дроппер определял ОС через
os.platform() и запускал платформенно-специфичный payload (T1059.007 - JavaScript, Execution):- macOS (darwin): AppleScript вызывал curl для загрузки бинарного RAT в /Library/Caches/com.apple.act.mond - имитация системного daemon Apple. Файл AppleScript удалялся сразу после выполнения
- Windows (win32): VBScript копировал powershell.exe в %PROGRAMDATA%\wt.exe (маскировка под Windows Terminal), затем загружал PowerShell RAT с C2
- Linux: Python RAT загружался в /tmp/ld.py и запускался через nohup для persistence (T1059.006 - Python, Execution)
После доставки payload дроппер выполнял три антифоренсик-операции: удалял setup.js, удалял package.json (содержащий postinstall hook - улику), переименовывал заранее подготовленный package.md в package.json - чистый stub v4.2.0 без следов вредоносного кода. После подмены директория node_modules/plain-crypto-js/ выглядела как обычная крипто-библиотека. Само наличие этой директории - индикатор компрометации, даже если содержимое кажется чистым.
Атрибуция: от drop path до YARA-правила WAVESHAPER
ThreatBook провёл атрибуцию через сравнение с трояном WAVESHAPER (Mandiant, февраль 2026, контекст активности UNC1069). Совпадения говорят сами за себя:- Drop path: /Library/Caches/com.apple.act.mond (axios) vs /Library/Caches/com.apple.mond (WAVESHAPER) - идентичные директории
- User-Agent:
mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)- полное совпадение. IE 8 на Windows XP в 2026 году - это визитная карточка, а не случайность - Команда сбора процессов:
sh -c ps -eo user,pid,command- полное совпадение - Внутреннее имя проекта macOS RAT - macWebT - связывается с модулем webT из кампании RustBucket, атрибутированной BlueNoroff (подгруппа Lazarus)
Код:
rule G_Backdoor_WAVESHAPER_1 {
strings:
$str1 = "mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)"
$str2 = "/tmp/.%s"
$str3 = "grep \"Install Succeeded\" /var/log/install.log"
$str4 = "sysctl -n hw.model"
$str5 = "sysctl -n machdep.cpu.brand_string"
$str6 = "sw_vers --ProductVersion"
condition:
all of them
}
GitHub Actions как вектор: компрометация AsyncAPI через CI/CD
Axios показал масштаб поражения через npm registry. AsyncAPI - следующая ступень: эксплуатация дизайна CI/CD пайплайна вместо кражи токена.Poisoned Pipeline Execution через незащищённые ветки
14 июля 2026 года, по данным Unit 42, атакующие скомпрометировали release pipelines четырёх GitHub-репозиториев AsyncAPI и опубликовали пять троянизированных пакетов: @asyncapi/generator@3.3.1, @asyncapi/specs@6.11.2, @asyncapi/specs@6.11.2-alpha.1, @asyncapi/generator-helpers@1.1.1 и @asyncapi/generator-components@0.7.1. Microsoft Security Blog подтвердил инцидент 16 июля 2026 года.Принципиальное отличие от axios: здесь не было компрометации аккаунта. Репозитории AsyncAPI поддерживали строгую branch protection и обязательный peer review на ветке main. А вот pre-production release-ветки -
next и schema - остались без защиты. Атакующие напрямую пушили коммиты в эти теневые ветки (T1677 - Poisoned Pipeline Execution), полностью минуя human review.Коммит запускал автоматизированный GitHub Actions workflow, который собирал и публиковал пакет. Инжектированный код выполнялся внутри CI-раннера, извлекал NPM_TOKEN и GITHUB_TOKEN из environment secrets, а затем программатически публиковал бэкдорированные версии в trusted scope @asyncapi. Branch protection на main - есть. На ветках, из которых CI реально публикует пакеты, - нет. Классическая ошибка.
Import-time payload вместо postinstall
По данным Unit 42, payload в AsyncAPI архитектурно отличался от axios. Вместо postinstall hook вредоносный код внедрялся в легитимные исходные файлы (index.js, validator.js, utils.js). Файл экспортировал нормально выглядящий объект schemas, но при вызовеrequire() функция main() запускала detached child process с обфусцированным скриптом (обработка через obfuscator.io).Скрипт определял ОС через process.platform и создавал директорию для payload, замаскированную под легитимную NodeJS-папку: %LOCALAPPDATA%\NodeJS (Windows), ~/Library/Application Support/NodeJS (macOS), ~/.local/share/NodeJS (Linux). Stage-2 RAT загружался из IPFS по hard-coded CID, записывался как sync.js и запускался с параметрами
detached: true, stdio: 'ignore', windowsHide: true. Родительский процесс вызывал child.unref() и завершался нормально - в логах тишина.Для persistence использовался user-scoped systemd service на Linux/macOS и Run key на Windows. Identity cache записывался в пути, мимикрирующие под системные: ~/Library/Application Support/com.apple.spotlight/index-v2.cache на macOS (подражание Spotlight), ~/.cache/mesa_shader_cache/gl_cache.bin на Linux (подражание кэшу Mesa GPU-шейдеров). Без знания этих путей - не найдёшь.
Переход от postinstall hooks к import-time execution - прямой ответ на рекомендацию
--ignore-scripts. Если payload выполняется при require() или import, отключение lifecycle scripts бесполезно.Самораспространяющаяся npm-малварь: worm-вариант 2025-2026
Отдельная категория - самораспространяющаяся npm-малварь. По данным Unit 42, первый по-настоящему self-propagating npm-червь (обозначенный как Shai-Hulud) обнаружен в сентябре 2025 года. Червь начинался с фишингового письма, замаскированного под уведомление npm security, захватывал credentials мейнтейнера, крал npm-токены и GitHub PAT, использовал их для автоматической публикации себя в дополнительные пакеты - без участия человека.По данным shattered.io со ссылкой на Group-IB, первая волна затронула более 180 пакетов. Вторая волна расширилась до почти 800, затронув проекты, связанные с Zapier, ENS Domains, PostHog и Postman. Socket зафиксировал около 500 затронутых пакетов с совокупным объёмом загрузок свыше 2,6 млрд в неделю.
Вариант 2.0 добавил деструктивное поведение: при отсутствии credentials для кражи червь повреждал локальные файлы. Unit 42 зафиксировал продолжение активности в апреле-мае 2026 года, при этом появление подражательной активности затруднило атрибуцию конкретным акторам. Червь, который распространяется через доверенные зависимости и уничтожает данные при невозможности дальнейшего распространения - принципиально иной класс угрозы, чем тайпсквоттинг или dependency confusion.
MITRE ATT&CK: маппинг supply chain техник Lazarus
Полный маппинг техник, задокументированных в кампаниях 2025-2026:| ID | Название | Тактика | Применение |
|---|---|---|---|
| T1195.001 | Compromise Software Dependencies | Initial Access | Внедрение phantom-зависимости (plain-crypto-js в axios) |
| T1195.002 | Compromise Software Supply Chain | Initial Access | Публикация троянизированных версий легитимных пакетов |
| T1677 | Poisoned Pipeline Execution | Execution | Коммит в незащищённую ветку AsyncAPI запускает автоматический workflow публикации |
| T1204.005 | Malicious Library | Execution | Код выполняется при установке или импорте пакета |
| T1059.007 | JavaScript | Execution | Дроппер setup.js, обфусцированные Node.js скрипты |
| T1059.006 | Python | Execution | Linux RAT /tmp/ld.py |
| T1027 | Obfuscated Files or Information | Defense Evasion | Reversed Base64 + XOR, control flow flattening, obfuscator.io |
| T1105 | Ingress Tool Transfer | Command and Control | Загрузка Stage-2 с C2 (sfrclak[.]com) или из IPFS по CID |
Детектирование и hardening npm supply chain атак
Чеклист: индикаторы компрометации и немедленные действия
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Hardening CI/CD пайплайна
- Lockfile-only установки в CI:
npm ciвместоnpm install. Запрет CI разрешать новые версии зависимостей. - Отключение lifecycle scripts:
--ignore-scriptsв.npmrc. Ограничение: не защищает от import-time payload (AsyncAPI-вариант), работает только против postinstall-дропперов. - Version pinning без caret/tilde ranges в package.json для критических зависимостей. При использовании ^1.x axios@1.14.1 разрешился за 89 секунд.
- Миграция на granular npm tokens с IP allowlisting, ограничением scope и expiration. Удаление всех classic tokens. Ограничение: не защищает от компрометации аккаунта с 2FA (как в случае jasonsaayman - метод обхода не установлен).
- Egress filtering в CI/CD раннерах - разрешить только registry.npmjs.org и внутренние зеркала. Блокировать прямой доступ к IPFS-гейтам.
- Provenance verification для пакетов с npm provenance. Ограничение: по данным Unit 42, при credential-based компрометации легитимный аккаунт публикует вредоносную версию с валидной подписью - provenance не спасает.
- Branch protection на ВСЕХ ветках, запускающих automated workflows. Не только main - каждая ветка, из которой CI может опубликовать пакет, должна требовать review.
- SBOM для production-артефактов. SBOM не предотвращает атаку, но сокращает время реагирования: при обнаружении скомпрометированного пакета моментально видно, какие сборки затронуты.
Ещё одна системная проблема, описанная shattered.io: dormant high-download packages - пакеты с миллионами загрузок, мейнтейнер которых давно забросил разработку. node-ipc, скомпрометированный 14 мая 2026 года (по данным StepSecurity), не обновлялся 21 месяц до появления вредоносного релиза. Download count не равен maintenance health. Библиотека может быть одновременно повсеместной и заброшенной - идеальная мишень.
Три инцидента - axios, AsyncAPI, Shai-Hulud - фиксируют эволюцию: от тайпсквоттинга и dependency confusion к целенаправленной компрометации ключевых пакетов и CI/CD инфраструктуры. По Group-IB (цитируется в shattered.io), шесть отдельных группировок сейчас работают по npm, PyPI и managed service providers - часть из них финансово мотивированные государственные акторы.
Мой опыт разбора npm-инцидентов за последний год показывает одну повторяющуюся ошибку: security-команды проверяют CVE в зависимостях, но не проверяют, кто опубликовал последнюю версию и когда мейнтейнер в последний раз коммитил в репозиторий. В supply chain атаках нет CVE - это не уязвимость в коде, это компрометация identity. AsyncAPI показал, что даже branch protection и code review не спасают, если release-ветки обходятся без review. А переход от postinstall к import-time execution обнуляет одну из немногих рабочих защит (
--ignore-scripts). Атакующие адаптируются быстрее, чем npm выкатывает hardening - и пока registry рассматривает валидный токен как единственную границу доверия для публикации, каждый мейнтейнер с long-lived token остаётся потенциальным вектором атаки на тысячи downstream-проектов. Формула на бумаге понятна, но supply chain compromise по-настоящему ощущается только когда разбираешь реальные артефакты - кто ещё не пробовал, на HackerLab.pro в категории web и forensics есть задачи на анализ вредоносных зависимостей, полезный стенд для отработки навыка.