ru
Назад к списку

Обзор крупнейшей NPM-атаки в истории: что это такое и при чем тут крипта

source-logo  getblock.net 10 Сентябрь 2025 13:00, UTC
image

8 сентября произошла крупнейшая в истории атака на NPM-инфраструктуру, направленная на пользователей криптовалют. Она могла затронуть миллиарды пользователей по всему миру, однако сообщество разработчиков вовремя обнаружило угрозу. GetBlock AML Research простым языком объясняет, что такое NPM и почему злоумышленники выбрали этот инструмент для взлома.

Что такое NPM

NPM — это крупнейший в мире каталог (библиотека) готовых программных «деталей» для разработчиков. Представьте себе магазин с миллионами маленьких деталей, из которых программисты собирают свои приложения. Вместо того чтобы каждый раз писать все с нуля, они берут эти готовые «кирпичики» и быстро строят программы и сервисы.

Эти «детали» называются пакетами. Их может создавать любой разработчик и выкладывать в общий доступ. Другие программисты используют эти пакеты в своих проектах — например, в сайтах, мобильных приложениях или даже в программах, связанных с криптовалютами.

И тут появляется связь с криптовалютами. Большая часть современных криптовалютных кошельков, бирж и других сервисов написана на языках программирования, где активно используют NPM-пакеты. Если злоумышленник внедрит вредоносный код в один из таких пакетов, то все программы, которые используют эту «деталь», тоже окажутся зараженными.

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

Как простая ошибка при сборке помогла обнаружить атаку

Все началось с непонятной ошибки при автоматической сборке в CI/CD-пайплайне, которую заметил один из разработчиков:

ReferenceError: fetch is not defined

Эта на первый взгляд мелкая ошибка оказалась первым признаком сложной атаки. Ошибка была прослежена до ее источника в небольшой зависимости error-ex. При дальнейшем расследовании оказалось, что в пакет был внедрен вредоносный код. В нем было обнаружено упоминание подозрительной функции checkethereumw, что сразу вызвало недоумение у разработчиков.

Злоумышленник встроил вредоносное ПО, предназначенное для обнаружения и кражи криптовалюты. Ошибка fetch возникла из-за того, что окружение Node.js было достаточно старым и не имело этой функции. В более новых системах атака могла бы пройти совершенно незаметно.

Масштаб воздействия на экосистему

Получив контроль над аккаунтом разработчика qix, злоумышленник опубликовал вредоносные обновления для ряда фундаментальных утилит JavaScript, включая:

  • chalk: ~300 млн загрузок в неделю
  • strip-ansi: ~261 млн загрузок в неделю
  • color-convert: ~193 млн загрузок в неделю
  • color-name: ~191 млн загрузок в неделю
  • error-ex: ~47 млн загрузок в неделю
  • simple-swizzle: ~26 млн загрузок в неделю
  • has-ansi: ~12 млн загрузок в неделю

Это не нишевые библиотеки, а важнейшие «строительные блоки», глубоко встроенные в зависимости множества проектов.

Разбор вредоносного кода: атака в два этапа

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

Вектор атаки 1: Пассивная подмена адресов

Код сначала проверял наличие объекта window.ethereum, который добавляют браузерные кошельки вроде MetaMask. Если кошелек не обнаруживался, запускался «пассивный» режим.

Вредоносный код заменял встроенные функции браузера для сетевых запросов, чтобы перехватывать все входящие и исходящие данные. Внутри были списки кошельков хакера для Bitcoin (BTC), Ethereum (ETH), Solana (SOL), Tron (TRX), Litecoin (LTC) и Bitcoin Cash (BCH).

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

Вектор атаки 2: Активное вмешательство в транзакции

Если кошелек все же обнаруживался, запускалась вторая, более опасная часть кода. Она перехватывала функции самого кошелька (например, sendTransaction).

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

Трекинг похищенных средств

Несмотря на масштабы атаки и миллиардные загрузки вредоносных файлов, злоумышленник получил лишь 0.1 ETH (около $430 по курсу на момент публикации статьи), которые хранятся на адресе:

0xFc4a4858bafef54D1b1d7697bfb5c52F4c166976

Интересный факт: 0.1 ETH были получены от одного пользователя с доменным именем leonard.eth (0xFD89d3831C6973fB5BA0b82022142b54AD9e8d46).

Визуализация: MistTrack

Граф связей одного из адресов хакера

Полный список кошельков злоумышленника опубликован на GitHub.

Как защитить свои проекты: срочные меры для разработчиков

Несмотря на то, что часть зараженных версий уже удалена из NPM, некоторые могут оставаться доступными. Поэтому:

  • используйте функцию overrides в package.json;
  • это позволит принудительно закрепить безопасные версии пакетов во всем проекте.

После внесения изменений необходимо удалить папку node_modules и файл package-lock.json, затем заново выполнить установку зависимостей (npm install), чтобы сформировать чистый lock-файл.

getblock.net