Слабый RNG в CryptoJS связали с кражами из кошельков на $5,69 млн

Компания Coinspect связала кражи криптоактивов как минимум на $5 690 922 со слабым генератором случайных чисел CryptoJS.lib.WordArray.random(). Уязвимый механизм применялся при создании seed-фраз в пяти приложениях: RRWallet, Bexo Wallet, NanChat, Bitcoin Libre и Milo. Анализ охватывает две волны вывода средств с 27 мая по 13 июля.
Проблемная функция появилась в JavaScript-библиотеке CryptoJS около 12 лет назад. Она использовала генератор Multiply-With-Carry, инициализированный через Math.random(), что не подходит для формирования криптографических секретов. Coinspect назвала кампанию атак Ill Bloom.
Почему seed-фразы оказались угадываемыми
Для 128- и 256-битной энтропии ожидаемое пространство перебора составляет соответственно 2^128 и 2^256 вариантов. По оценке Coinspect, слабый генератор сокращал его примерно до 2^39 и 2^47. Такой объём исследователи считают доступным для перебора на обычном оборудовании.
Специалисты воспроизвели цепочку атаки: перечисляли возможные результаты генератора, преобразовывали их в фразы BIP39, получали адреса и проверяли их по публичным данным блокчейнов. Последующее хеширование или обработка PBKDF2 не возвращают утраченную энтропию.
Первая волна 27 мая затронула 431 аккаунт и принесла злоумышленникам около $3,14 млн. Во второй, продолжавшейся с 30 мая по 13 июля, было похищено $2,55 млн с адресов, связанных с 522 seed-фразами. В неё вошёл перевод примерно 2,18 млн USDT с одного адреса Tron 4 июля. Всего исследователи отследили 2 114 seed-фраз и связанные адреса в Bitcoin, Ethereum, Tron, Rootstock и Polygon.
Какие приложения затронуты
NanChat подтвердил проблему в версиях до 1.3.0 и выпустил исправление в версии 1.3.0. В приложение добавили инструмент для создания новой seed-фразы и перевода средств. Bitcoin Libre, по сведениям Coinspect, устранил проблему в версии 4, выпущенной в июле 2024 года.
Для Bexo Wallet исправление заявлено в версии 20.1.0, но на 6 августа обновлённые сборки ещё не были загружены в магазины приложений. RRWallet и Milo прекращены и исправления для них не выпускались. Coinspect подчёркивает, что не может подтвердить полный перечень затронутых кошельков: старые версии могли исчезнуть из магазинов и маркетплейсов расширений.
История исправления CryptoJS
В CryptoJS 3.2.0 и 3.2.1 разработчики временно перешли на нативный криптографический источник случайности. Однако в версии 3.3.0 слабый код вернули, посчитав изменение несовместимым. Постоянное исправление появилось только в CryptoJS 4.0.0 в феврале 2020 года. Мейнтейнер CryptoJS Evan Vosberg 5 августа опубликовал критическое уведомление GHSA-rg76-677x-56q9 с оценкой CVSS 9.0.
Наличие CryptoJS в зависимостях само по себе не означает эксплуатацию: опасность возникает, только если уязвимую функцию применяли для генерации чувствительных значений. Одним из путей попадания проблемы в кошельки Coinspect назвала fork ferrumnet/bip39 для React Native, заменивший нативную криптографическую случайность upstream-пакета bip39 на CryptoJS. Риски, возникающие при использовании доверенных, но небезопасных компонентов, укладываются в картину, описанную в цепочки доверия становятся целью атакующих, где цепочки доверия становятся целью атакующих.
Что делать пользователям и компаниям
Обновление кошелька не защищает seed-фразу, созданную уязвимой версией. При её импорте в другой программный или аппаратный кошелёк она остаётся предсказуемой. Пользователям затронутых приложений следует создать новую фразу через безопасный механизм и перевести на неё средства, ориентируясь на официальные инструкции разработчиков.
Аппаратно созданные seed-фразы и большинство актуальных программных кошельков, по оценке Coinspect, не затронуты. Для бизнеса этот случай показывает необходимость аудировать не только перечень библиотек и версий, но и фактическое использование криптографических API в коде, который создаёт ключи, пароли и фразы восстановления.

