脆弱性 / THREAT / CRYPTO WALLET
CryptoJSの弱い乱数がウォレット流出の裏に — 「Ill Bloom」はなぜ5つのアプリに波及したか
復元フレーズを守るはずの乱数生成が、通常のPCで列挙できる大きさまで縮んでいた。Coinspectの調査を軸に、流出の仕組み、影響を受けた5アプリ、利用者が今取れる行動を整理する。
2026年8月、ブロックチェーンセキュリティ企業のCoinspectは、暗号資産ウォレットの復元フレーズ生成に関わる一連の調査「Ill Bloom」の結果を公表した。調査は5月に始まったウォレットからの不正送金を起点とし、その背後に、JavaScriptの暗号ライブラリであるCryptoJSの乱数生成関数の脆弱性があったことを明らかにした。Coinspectのオンチェーン分析では、5月末以降の2波の不正送金で、測定可能な被害は少なくとも約570万ドル(概算で8億円規模)に上る。
乱数が「弱い」と何が起きるか
復元フレーズ(シードフレーズ)は、ウォレットの秘密鍵を復元するための文字列だ。通常は乱数生成器から得たエントロピーをBIP39などの仕様に沿って単語列へ変換して作られる。乱数生成が十分に強ければフレーズの候補は天文学的な数になり、総当たりは現実的でない。
Coinspectの分析によると、問題となった CryptoJS.lib.WordArray.random() は、2014年6月にMultiply-With-Carry(MWC)方式の生成器として導入され、そのシードに Math.random() を使っていた。この関数で生成したエントロピーは、128ビットの鍵であれば探索空間がおよそ2^128から2^39へ、256ビットであれば2^256から2^47へ縮小していたという。2^39は数億程度の大きさで、通常の計算資源でも列挙できる。Coinspectは実際に候補を列挙し、BIP39フレーズへ変換してアドレスを導出し、公開ブロックチェーンのデータと照合するという攻撃チェーンを再現している。
影響を受けた5つのウォレットアプリ
Coinspectが特定したのは、復元フレーズの生成にこの関数をエントロピー源として使っていた5つのアプリだ。
- RRWallet — 開発終了。修正の予定なし。
- Bexo Wallet — バージョン20.1.0で修正済みとされるが、確認時点で更新版の配布はまだ行われていなかった。
- NanChat — 1.3.0未満が影響を受け、1.3.0で修正。8月6日時点で、名前が公表されたアプリの中で唯一の公式アドバイザリ公開例。
- Bitcoin Libre — 2024年7月リリースのバージョン4で修正済み。
- Milo — 開発終了。修正の予定なし。
Coinspectは、これらが7月に名前を伏せて言及した5つのウォレットと同じだと述べている。また、調査の限界として、影響を受けたウォレットをすべて特定できたとは限らないことを指摘している。すでにアプリストアや拡張機能マーケットプレイスから削除されたものや、修正版と置き換わって旧バージョンを入手できないものは、検査の対象にならなかったためだ。
流出の実態 — 2波で約570万ドル
Coinspectのオンチェーン分析では、攻撃は2つの波で実行された。
- 5月27日の波 — 431アカウントから約314万ドル。
- 5月30日から7月13日の波 — 522のシードに関連するアドレスから約255万ドル。うち約218万USDTは7月4日に単一のTronアカウントから送金された。
後の分析では、Bitcoin、Ethereum、Tron、Rootstock、Polygonにまたがる2,114のシードと関連アドレスが追跡されている。7月13日時点での測定被害は合計5,690,922ドルで、Coinspectはこれを「下限値」と表現している。ブロックチェーンデータからの推計では、影響を受ける可能性のある人口はEVM互換ネットワークとBitcoinで数千規模に上るという。
「Ill Bloom」という名前は、影響を受けた生成器が最初に生み出す弱いフレーズ「illness blossom」に由来する。2023年7月にLibbitcoin Explorerの脆弱性(CVE-2023-39910)を突いて大規模な不正送金が起きた「Milk Sad」と、名前の付け方も構造も似ている。乱数生成の品質が鍵の強度を決めるという教訓が、3年で再演された格好だ。
ライブラリ側の経緯とアドバイザリ
CryptoJS側の修正経緯は複雑だ。2014年6月にMWC生成器が導入された後、リリース3.2.0と3.2.1はネイティブの暗号論的乱数へ切り替えたが、3.3.0で「破壊的変更」と判断されて弱い実装へ巻き戻された。同じ3.x系の中でのアップグレードが、修正済みから脆弱なバージョンへ移行する結果になり得る。2020年2月の4.0.0でネイティブ乱数への復帰が恒久化された。
8月5日には、メンテナのEvan VosbergがGitHub Security Advisory(GHSA-rg76-677x-56q9)を公開した。Critical、CVSSスコア9.0で、パッケージの該当範囲は4.0.0未満の全リリースとされている(3.2.0・3.2.1の例外を除く)。ただし、アドバイザリは「依存関係に含むだけでは影響を受けない。セキュリティ上重要な値の生成に脆弱な関数を使った場合に限られる」と明記している。パッケージの該当範囲は、実際に悪用可能なアプリの集合より広い。
なお、ウォレットソフトウェアへの侵入経路としては、React Native向けにbip39をフォークした ferrurnet/bip39 が、本来のネイティブ乱数をCryptoJSへ置き換えていたことが一例として挙げられている。これが唯一の経路ではない。
利用者が取るべき行動
いちばん重要な点は、アプリを更新しても既存の復元フレーズは修復されないことだ。一度弱い乱数で生成されたフレーズは、その後のハッシュ処理やPBKDF2、パッケージの更新によって失われたエントロピーを取り戻せない。フレーズの強度は生成された時点で決まる。
- 影響を受けた可能性のある経路でフレーズを生成した利用者は、安全な環境で新しいシードを作成し、資金を移す。
- 影響を受けたフレーズをハードウェアウォレットにインポートしている場合も、そのフレーズは推測可能なままなので、作り直す対象になる。
- Coinspectは調査サイト上で公開アドレスチェッカーを提供しており、自分のアドレスが影響を受けたアドレス集合に含まれるかを確認できる。
- ハードウェアウォレットで生成されたシードと、ほとんどの現行ソフトウェアウォレットは影響を受けていないとCoinspectは述べている。
開発者が確認すべきこと
JavaScript/TypeScriptのプロジェクトでCryptoJS(4.0.0未満)を依存関係に持つ場合、それが鍵・シード・トークンなどのセキュリティ上重要な値の生成に使われていないか確認する。ウォレットや鍵管理機能を持つアプリでは、依存関係の推移的な解決にも注意が必要だ。bip39のフォークやウォレットSDK経由で、気づかないうちに脆弱な乱数経路を抱えている可能性がある。
乱数生成の品質は、鍵の強度そのものだ。「Ill Bloom」は、一度入り込んだ弱い乱数が、ライブラリの更新をすり抜けて何年も生き続けることを示している。
出典: Coinspect — Ill Bloom: Investigating a Wallet Generation Vulnerability During Active Exploitation / The Hacker News — CryptoJS Weak RNG Behind $5.7 Million in Drains Affects Five Crypto Wallet Apps / GitHub Advisory GHSA-rg76-677x-56q9
この記事は、Microsoft、Apple、MITRE ATT&CKなどの公開情報をもとに SECURITY MEDIA 編集部が日本語で再構成した編集記事です。公開時点の情報に基づく解説であり、個別の環境への診断・対応を保証するものではありません。