Modern Frontend CVEs

対象CVE: CVE-2026-71851

[深刻な脆弱性解説] crypto-jsにおける暗号学的に安全でない乱数生成(CVE-2026-71851)とフロントエンドへの影響

`crypto-js`ライブラリの`CryptoJS.lib.WordArray.random()`関数に、暗号学的に安全でない乱数生成の脆弱性が発見されました。この脆弱性が悪用されると、秘密鍵や復元フレーズなどのセキュリティ上重要な情報が特定され、資産が盗まれる可能性があります。

はじめに:`crypto-js`の深刻な脆弱性について

日々、JavaScriptベースのアプリケーション開発に携わるフロントエンドエンジニアの皆さん、こんにちは。今回は、広く利用されているJavaScriptの暗号化ライブラリ`crypto-js`に発見された、極めて深刻な脆弱性GHSA-rg76-677x-56q9 (CVE-2026-71851) について解説します。この脆弱性は「critical」と評価されており、セキュリティ上重要な値の生成に`crypto-js`を使用している場合、甚大な被害につながる可能性があります。

脆弱性の概要:暗号学的に安全でない乱数生成

この脆弱性の核心は、`crypto-js`のバージョン`4.0.0`未満に存在する`CryptoJS.lib.WordArray.random()`関数が、暗号学的に安全な乱数(CSPRNG)ではないという点にあります。この関数は、`Math.random()`をシードとするカスタムのMultiply-With-Carry (MWC) PRNG(擬似乱数生成器)を使用していました。一般的に`Math.random()`は予測可能であり、セキュリティ用途での使用は避けるべきです。

その結果、この関数によって生成される乱数のエントロピー(不確実性)は非常に低く、公称128ビットまたは256ビットのエントロピーが要求されていても、実質的には約2^39または2^47という限られた探索空間しか持ちません。これは、一般的なハードウェアでも総当たり攻撃(ブルートフォースアタック)によって容易に破られてしまうレベルです。

特に、暗号資産ウォレットアプリケーションでBIP39リカバリーフレーズ(シードフレーズ)の生成源としてこの脆弱な関数が使用されたケースが確認されており、これが深刻な問題を引き起こしています。

<strong>重要な注意点:</strong>単に`crypto-js < 4.0.0`に依存しているだけでは、この脆弱性の影響を受けません。<strong>`CryptoJS.lib.WordArray.random()`関数が、秘密鍵、パスワードのソルト、暗号化キーなどのセキュリティ上機密性の高い値の生成に使用されている場合にのみ影響を受けます。</strong>

実際の攻撃と甚大な影響

セキュリティ企業Coinspectは「Ill Bloom」と名付けた調査を通じて、この脆弱性の概念実証(Proof of Concept: PoC)だけでなく、実際の攻撃による資産の盗難を文書化しています。攻撃者は以下の手順で資産を盗み出しました。

1. 脆弱な`WordArray.random()`の挙動を再実装。<br>2. underlying PRNGの可能な出力を列挙。<br>3. 候補となるエントロピー値を有効なBIP39リカバリーフレーズに変換。<br>4. 関連する派生パスとネットワーク全体で秘密鍵とアドレスを導出。<br>5. 導出されたアドレスを公開ブロックチェーンデータと比較。<br>6. 資金のあるアドレスを制御する秘密鍵を復元。

2026年7月13日時点で、この脆弱性を悪用した2つのイベントで約500万ドル相当の資産が盗まれたことが確認されています。さらに、この脆弱性の影響は永続的です。

<ul><li>脆弱なコードで一度生成された秘密は、ライブラリやウォレットを更新しても安全になりません。</li><li>脆弱なコードで生成されたリカバリーフレーズを更新されたソフトウェアやハードウェアウォレットにインポートしても、問題は解消されません。</li><li>以前に生成された秘密は、無期限に悪用される可能性があります。</li><li>影響を受けるアドレスへの将来の入金も盗まれる可能性があります。</li></ul>

フロントエンドエンジニアが取るべき対策

あなたのプロジェクトで`crypto-js`を使用している場合、以下の対策を速やかに実行してください。

<ol><li>`crypto-js`をバージョン`4.0.0`以降にアップグレードしてください。</li><li>可能であれば、`CryptoJS`の乱数生成をWeb Crypto API (ブラウザ環境) またはNode.jsの`crypto`モジュール (Node.js環境) のような、プラットフォームネイティブの暗号APIに置き換えることを強く推奨します。これらのAPIは暗号学的に安全な乱数を提供します。</li><li>直接的、間接的(依存パッケージの依存関係として)を問わず、`crypto-js`のバージョンが`4.0.0`未満のものが存在しないか、依存関係ツリーを監査してください。`npm list crypto-js`や`yarn why crypto-js`などのコマンドで確認できます。</li><li>`CryptoJS.lib.WordArray.random()`が、パスワード、秘密鍵、認証トークンなどのセキュリティ上機密性の高い値の生成に使用されていないか確認してください。</li><li>脆弱な生成パスが存在した期間とアプリケーションバージョンを特定し、その期間に生成された長期秘密(例:ユーザーの秘密鍵、シードフレーズ)は、すべて侵害されたものとみなしてください。</li><li>影響を受けるすべての長期秘密をローテーション(再生成)してください。これは、ユーザーに新しい秘密の生成と移行を促す必要がある場合があります。</li><li>影響を受けるユーザーに対し、ライブラリの更新だけでは過去に生成された秘密は安全にならないことを明確に通知してください。</li></ol>

もしあなたのアプリケーションが暗号資産ウォレットとして機能し、ユーザーに影響が及ぶ可能性がある場合、ユーザーには以下の行動を促す必要があります。

<ul><li>信頼できるソースから新しく生成されたリカバリーフレーズで新しいウォレットを作成し、資産をそのウォレットのアドレスに移行する。</li><li><strong>既存のリカバリーフレーズを新しいウォレットにインポートしない。</strong></li></ul>

おわりに

この脆弱性は、依存ライブラリの選定と使用方法におけるセキュリティ意識の重要性を改めて浮き彫りにしました。特に、暗号関連の機能を使用する際は、その実装が暗号学的に安全であるかを常に確認する必要があります。

Coinspectは、自身のIll Bloom調査サイトで、既知の流出アドレスデータセットに含まれるアドレスをチェックできるツールを提供しています。これはあくまで公開ブロックチェーンアドレスのみを入力するものであり、リカバリーフレーズや秘密鍵などを入力しては<strong>絶対にいけません。</strong>

<ul><li>Ill Bloom研究サイトと公開アドレスチェッカー: <a href="https://illbloom.org/" target="_blank">https://illbloom.org/</a></li><li>Coinspect調査概要: <a href="https://www.coinspect.com/blog/ill-bloom-investigation/" target="_blank">https://www.coinspect.com/blog/ill-bloom-investigation/</a></li></ul>

フロントエンドエンジニアとして、私たち自身がセキュリティの最前線にいることを認識し、安全なアプリケーション開発を心がけましょう。

← ブログ一覧に戻る