過去1週間(2026年2月2日~2月8日)、BlockSecは6件の攻撃インシデントを検出し分析しました。総推定損失額は約380万ドルでした。以下の表にこれらのインシデントの概要を示し、各ケースの詳細な分析は後続のセクションで提供します。
| 日付 | インシデント | タイプ | 推定損失額 |
|---|---|---|---|
| 2026/02/02 | CrossCurveインシデント | アクセス制御 | 約280万ドル |
| 2026/02/03 | GYDインシデント | 不適切な入力検証 | 約70万ドル |
| 2026/02/05 | SOFIトークンインシデント | トークン設計上の欠陥 | 約29,600ドル |
| 2026/02/05 | 未知のステーキングプロトコルインシデント | 不適切な入力検証 | 約71,600ドル |
| 2026/02/07 | LZMultiCallプロトコルインシデント | 任意のコール | 約142,000ドル |
| 2026/02/08 | 未知のプロトコルインシデント | 不適切な入力検証 | 約63,000ドル |
1. CrossCurveインシデント
概要
2026年2月2日、CrossCurveプロトコルが悪用され、約280万ドルの損失が発生しました。根本原因は、ReceiverAxelarコントラクトが、標準のAxelarゲートウェイ検証プロセスをバイパスする、権限のないexpressExecute()関数を公開していたことです。レシーバーは、外部から提供されたデータに基づいたピアアドレスチェックしか行いませんでした。その結果、攻撃者は悪意のあるクロスチェーンコールを構築し、バーンおよびアンロックメカニズムをトリガーして、999,787,453e18 EYWAトークンが攻撃者に不正にリリースされる事態を招きました。
背景
CrossCurveはEywa.Fiによって開発されたクロスチェーンブリッジプロトコルであり、Axelarクロスチェーンメッセージングフレームワーク上に構築されています。
Axelarの意図されたセキュリティモデルでは、クロスチェーンメッセージはAxelarゲートウェイによって中継され、宛先チェーンでvalidateContractCall()を通じて明示的に検証される必要があります。ゲートウェイによって暗号学的に承認されたメッセージのみが実行に進むことが許可されます。
レイテンシを削減するため、Axelarはエクスプレス実行メカニズムも提供しており、レシーバーコントラクトはゲートウェイが検証を完了する前に、楽観的にメッセージを実行することができます。この設計では、信頼されたエグゼキューターのみがエクスプレス実行パスを呼び出せるように、厳格なアクセス制御が必要となります。さもないと、検証されていないクロスチェーンメッセージが早期に処理される可能性があります。
脆弱性分析
根本原因は、ReceiverAxelarが、Axelarゲートウェイの承認なしに特権のある_execute()パスに直接到達できる、権限のないexpressExecute()関数を公開していたことです。
Axelarの正しいセキュリティモデルでは、クロスチェーンメッセージはまずゲートウェイによって証明バック実行を通じて承認され、次に宛先チェーンでvalidateContractCall()を通じて検証される必要があります。これは、(commandId, sourceChain, sourceAddress, contractAddress, payloadHash)を単一の承認済み実行にバインドします。
しかし、expressExecute()パスはこの検証を完全にスキップしました。それは、攻撃者が制御可能であったsourceChainとsourceAddressに基づくピアチェックにのみ依存しており、そのため実質的なセキュリティを提供しませんでした。これにより、攻撃者は偽造されたメッセージを提供し、receiveDataブランチに強制し、最終的にEywa CLP Portalのunlock()をトリガーする任意のペイロードを実行し、クロスチェーン資産の不正リリースにつながりました。
攻撃分析
-
ステップ1:攻撃者は、
sourceChain、sourceAddress、およびpayloadを偽装して、expressExecute()を直接呼び出しました。expressExecute()はゲートウェイ検証をバイパスして_execute()に直接進むため、残された唯一のセキュリティ対策はピアアドレスホワイトリストチェックでした:require(peers[sourceChain] == sourceAddress.toAddress())。このチェックは、sourceChainとsourceAddressの両方が外部から提供されたため、不十分でした。正しいホワイトリストに登録されたピアアドレスを提供することで、攻撃者はこれをバイパスしました。 -
ステップ2:偽造された
payloadは、その後Receiver.receiveData()ブランチに転送されました。resume()関数は、悪意のあるペイロードに基づいてクロスチェーン操作PortalV2.unlock()を実行し、攻撃者への資金の不正なアンロックにつながりました。
結論
このインシデントは、クロスチェーンレシーバーコントラクト内の加速実行パスにおける不十分なアクセス制御によって根本的に引き起こされました。expressExecute()を権限のない関数として公開し、外部から提供されたピア情報のみに依存することで、CrossCurveは事実上、攻撃者がAxelarゲートウェイのセキュリティ保証をバイパスし、任意のクロスチェーンペイロードを実行できるようにしました。
将来同様のリスクを軽減するため、エクスプレスまたはオプティミスティック実行メカニズムを統合するクロスチェーンプロトコルは、以下を行うべきです。
-
高速パス実行関数に厳格な呼び出し元認証を強制し、信頼されたリレイヤーまたはゲートウェイのみがそれを呼び出せるようにする。
-
承認の唯一の基準として、攻撃者が制御可能なメタデータ(ソースチェーンまたはアドレスなど)に依存しない。
-
エクスプレス実行を特権操作として扱い、標準の検証済み実行パスと同等の多層防御チェックを適用する。
これらの原則を注意深く遵守することは、クロスチェーンシステムを設計する上で極めて重要です。単一の検証バイパスが複数のネットワークにわたるシステム的な資産損失につながる可能性があります。
2. GYDインシデント
概要
2026年2月3日、GYDプロトコルが悪用され、約70万ドルの損失が発生しました。根本原因は、CCIPレシーバーが攻撃者が制御するメッセージデータを実行コンテキストとして信頼していたことです。このエクスプロイトは、Arbitrumから送信されたCCIPメッセージによってトリガーされました。このメッセージはメッセージングレイヤーで正しく認証されましたが、デコードされたペイロードは後で_ccipReceive()で任意の外部コールを実行するために使用されました。デコードされたレシーピエントをGYDトークンコントラクトに設定し、approve(attacker, type(uint256).max)のコールデータを提供することで、エスクローは意図せずGYD残高に対する無制限の承認を付与しました。その後、攻撃者はtransferFrom()を通じて資金を drain しました。
背景
GydL1CCipEscrowコントラクトは、Chainlink CCIP標準上に構築されたクロスチェーン資産エスクローコントラクトです。ユーザーはL1のこのコントラクトにGYDトークンをロックし、CCIP経由で宛先チェーンにクロスチェーンメッセージを送信します。逆に、クロスチェーンメッセージがエスクローに到着すると、CCIPはその認証を検証し、_ccipReceive()をトリガーします。この関数は、受信したコールデータを解析してtx.recipientとdataを抽出し、解析されたパラメータ(金額とレシーピエント)に基づいてGYD転送またはアンロックロジックを実行します。dataが空でない場合、recipient.functionCall(data)を通じて任意の外部コールを実行します。
脆弱性分析
中核となる脆弱性は、GydL1CCipEscrowがクロスチェーンメッセージからデコードされたtx.recipientアドレスを検証しないことです。攻撃者はtx.recipientをイーサリアム上のGYDトークンコントラクトアドレスに設定し、dataをapprove(attacker, type(uint256).max)として作成することができます。エスクローコントラクトは大量のロックされたGYDトークンを保有しているため、この無制限の外部コールにより、エスクローはGYDトークンの全承認を攻撃者に付与し、攻撃者はその後transferFrom()を通じて全資金を drain することができます。
攻撃分析
-
ステップ1:攻撃者はArbitrum上で悪意のあるCCIPメッセージを開始し、
tx.recipientをイーサリアム上のGYDトークンコントラクトアドレス、tx.dataをapprove(attacker, type(uint256).max)のエンコードされたコールデータとして指定しました。 -
ステップ2:メッセージがイーサリアムで処理された際、
GydL1CCipEscrowコントラクトの_ccipReceive()関数は、tx.recipientを検証せずにGYDトークンコントラクト上で承認を実行しました。その後、攻撃者はGYDトークン上でtransferFrom()を呼び出し、エスクローされた全資金を drain しました。
結論
このインシデントの根本原因は、GydL1CCipEscrowコントラクトがクロスチェーンメッセージを処理する際にデコードされたペイロードを検証しなかったことで、攻撃者が悪意のあるクロスチェーンコールを構築できたことです。クロスチェーンブリッジメッセージングにおいて、開発者は以下を行うべきです。
-
エスクローからのトークンコントラクトへの直接コールを禁止する:クロスチェーンメッセージペイロードがエスクローされたトークンコントラクトを呼び出せないようにする。
-
実行ターゲットのホワイトリストを実装する:
tx.recipient(またはtx.target)を、定義された信頼できるアドレスのセットに制限する。
3. SOFIトークンインシデント
概要
2026年2月5日、BNB Chain上のSOFIトークンが悪用され、約29,600ドルの損失が発生しました。
根本原因は、トークンのオーバーライドされた_transfer()関数内に実装された欠陥のあるバーンメカニズムでした。遅延バーンロジックを悪用し、PancakeSwapの流動性プールから直接トークンを削除して、その後のsync()をトリガーすることで、攻撃者はSOFI価格を人為的にインフレさせることができました。繰り返し転送とスワップを通じて、攻撃者はプールから過剰なUSDT流動性を抽出し、フラッシュローンを利益とともに返済しました。
背景
SOFIはBNB ChainにデプロイされたカスタムERC-20トークンです。標準的なERC-20実装とは異なり、SOFIトークンは内部の_transfer()関数をオーバーライドして、売却操作中のトークンバーンに関連する追加ロジックを埋め込んでいます。
このトークンは、PancakeSwapスタイルの定数積AMMプール(SOFI–USDT)で取引されています。このようなプールでは、トークン価格はトークン準備金の比率から導き出されます。プール残高の予期せぬ変更、特にスワップによって引き起こされない変更は、直接価格を操作することができます。
この設計では、トークンコントラクト自体が転送中に流動性プールとやり取りするため、プールの準備金会計は、純粋なAMMメカニズムではなく、トークン側のロジックに依存します。
脆弱性分析
脆弱性は、SOFIのバーンメカニズムと_transfer()内のプールインタラクションの組み合わせにあります。
SOFIトークンが流動性プールアドレスに転送されると、コントラクトはその転送を売却と解釈し、内部アキュムレータ変数waitBurnTokenAmountをインクリメントします。しかし、累積された金額はすぐにバーンされません。代わりに、後続のプールへの転送時にプールからバーンされ、その後プールのsync()関数が呼び出されます。
この設計は2つの重大な問題を引き起こします。
-
直接的なプール残高操作 プールから直接トークンをバーンすると、USDTの流出に対応せずにSOFI準備金が減少するため、AMMの不変条件に違反し、SOFI価格が人為的に上昇します。
-
遅延および攻撃者制御可能な実行 バーンは将来の転送時にのみ発生するため、攻撃者はバーンと
sync()が発生するタイミングを正確に制御でき、価格歪みから利益を得るための位置取りを可能にします。
その結果、プール価格はもはや実際の需給ダイナミクスを反映せず、抽出可能なアービトラージを可能にします。
攻撃分析
-
ステップ1:フラッシュローンを通じて
USDTを借入します。 -
ステップ2:
SOFI–USDTプールでUSDTをSOFIにスワップします。 -
ステップ3:
SOFIをプールに転送し、skim()を呼び出して、損失を最小限に抑えながらwaitBurnTokenAmountを増加させます。 -
ステップ4:再度
SOFIをプールに転送してバーン+sync()をトリガーし、SOFI価格を上昇させてから、SOFIをUSDTにスワップします。 -
ステップ5:ステップ4を繰り返します。新しく累積された
waitBurnTokenAmountは次の転送時にのみバーンされるため、複数のイテレーションが必要です。 -
ステップ6:プールから
USDTを drain し、フラッシュローンを返済します。
結論
このインシデントは、最終的にはAMMプール残高を直接操作する安全でないトークンサイドバーンメカニズムによって引き起こされました。遅延バーンロジックを_transfer()内に埋め込み、流動性プール自体からバーンを実行することで、SOFIトークンは定数積AMMの基本的な前提を破り、決定論的な価格操作を可能にしました。
_transfer()をオーバーライドするERC-20トークンについて、開発者は特に以下のことを避けるように注意する必要があります。
-
流動性プールから直接トークンをバーンする
-
プール残高に影響を与える遅延またはステートフルなメカニズムを導入する
-
トークンロジックをAMMの内部と過度に密接に結合する
一般的に、トークノミクス関連のロジックは、プール残高を任意に変更することを決して許可されるべきではありません。たとえわずかな偏差であっても、流動性を drain するために繰り返し悪用される可能性があります。
4. 未知のステーキングプロトコルインシデント(2026年2月5日)
概要
2026年2月5日、イーサリアム上の未知のステーキングプロトコルが悪用され、約71,600ドルの損失が発生しました。
根本原因は、引き出し中に検証されていない、ユーザー提供の入力データにプロトコルが依存していたことでした。具体的には、プロトコルは攻撃者が制御するrouterCalldataとLP金額を検証なしにPendle Routerに転送しました。プロトコルのLPポジション全体を削除し、自身を受信者として設定するコールデータを作成することで、攻撃者はボールトが保有する全資産を drain することができました。
背景
未知のステーキングプロトコルは、Pendle Finance上に構築されたシンプルなイールドボールトです。ユーザーはボールトに資産を預け入れ、ボールトはそれらの資産をPendle Routerにルーティングしてイールドベアリングポジションをミントします。内部的には、預け入れはSYに変換され、PTとYTに分割され、組み合わされてPendle LPトークンが形成されます。
プロトコルは、すべてのLPトークンをカストディ保有し、各ユーザーの預け入れられた基盤資産額の内部会計を維持します。ユーザーが引き出す際、ボールトはPendle Routerを通じてLPトークンを償還し、対応する資産をユーザーに返却します。
脆弱性分析
根本原因は、検証されていない入力データです。withdrawWithCalldataMultiToken()関数は、基盤トークン、基盤金額、LP金額、およびrouterCalldataの4つのパラメータを受け取ります。ユーザーの記録された基盤残高が十分であるかどうかのチェックしか行いませんが、LP金額やrouterCalldataの内容は検証しません。Pendle Routerを通じて流動性を削除する際、コントラクトはrouterCalldataに埋め込まれたパラメータに完全に依存します。その結果、攻撃者はプロトコルの全LP残高を渡して、自身を受信者として設定することで、プロトコルが保有する全資産を drain することができました。
攻撃分析
-
ステップ1:
USDCのフラッシュローンを借入します。 -
ステップ2:少額の
USDCをプロトコルに預け入れます。これにより、資金がPendle Routerにルーティングされて流動性が追加され、LPがミントされます。 -
ステップ3:
routerCalldataを悪意のあるものに作成し、receiverを攻撃者に、lpAmountをプロトコルの全LP残高に設定して、withdrawWithCalldataMultiToken()を呼び出します。 -
ステップ4:プロトコルは、攻撃者が制御するパラメータを使用して
Pendle Routerを通じて流動性を削除し、全資産を攻撃者に送信します。 -
ステップ5:受信した資産を
USDCにスワップし、フラッシュローンを返済し、残りを利益として保持します。
結論
このインシデントは、最終的には、重要な引き出しパス内の攻撃者が制御する外部入力への無条件の信頼によって引き起こされました。検証なしに任意のコールデータとLP金額を外部ルーターに転送することで、プロトコルはユーザーが資格のあるシェアを超えて引き出しを実行することを許可し、ボールトのPendleポジションの完全な drain につながりました。
本番ボールトおよびイールド戦略、特に複雑な外部ルーターを統合するものについては、開発者は以下を行うべきです。
-
コールデータを含む、ユーザーが提供するすべての入力を信頼できないものとして扱い、厳密に検証する。
-
LP金額や受信者などの機密パラメータは、ユーザーから受け入れるのではなく、内部で導出する。
-
内部会計と外部実行結果との一貫性を強制することで、多層防御を適用する。
これらを怠ると、単一の引き出しコールがプロトコルが保有する全資産の侵害につながる可能性があります。
5. LZMultiCallプロトコルインシデント
概要
2026年2月7日、LZMultiCallインシデントにより、イーサリアムで約142,000ドルの損失が発生しました。
このインシデントは、LZMultiCallコントラクト自体の脆弱性によるものではなく、ユーザーの誤用によるものでした。LZMultiCallはステートレスなバッチ実行コントラクトであり、資産をカストディしたり、ERC-20承認を保持したりするように設計されていません。しかし、一部のユーザーは誤ってコントラクトにトークン承認を付与していました。その後、攻撃者はこれらの残存する承認を悪用し、悪意のあるコールデータでexecute()を呼び出してtransferFrom()を呼び出し、影響を受けたユーザーからトークンを drain しました。
背景
LZMultiCallは汎用的なバッチ実行ユーティリティコントラクトです。その意図された目的は、ユーザーが複数のコールを単一のトランザクションにバンドルし、ユーザー提供のコールデータをターゲットコントラクトに転送できるようにすることです。
重要ながら、LZMultiCallはステートレスで非カストディアルになるように設計されています。資産を保持するためのものではなく、ユーザーがそれにERC-20承認を付与すべきでもありません。LZMultiCallに付与されたいかなるトークン承認も、その明示的な使用前提条件に違反し、コントラクトは呼び出し元に代わって任意のコールを転送できるため、ユーザーをリスクにさらします。
脆弱性分析
LZMultiCallは設計どおりに機能しましたが、ユーザーが誤ってERC-20承認を付与すると、その権限のないexecute()関数が悪用可能になりました。コントラクトは任意のコールデータを任意のターゲットに転送するため、攻撃者はトークンコントラクトでtransferFrom(victim, attacker, amount)をエンコードしたコールデータでexecute()を呼び出し、事実上、残存するすべての承認を drain できました。
攻撃分析
- 攻撃者は、トークンコントラクトをターゲットとする悪意のあるコールデータで
execute()を呼び出し、transferFrom()を使用して、LZMultiCallに誤って承認を付与していたユーザーからトークンを転送しました。
結論
このインシデントは、最終的にはステートレスなバッチ実行コントラクトの明示的な使用前提条件を違反したことによって引き起こされました。LZMultiCallは、資金をカストディしたり、ERC-20承認を保持したりするために設計されたものではありませんでした。ユーザーが誤って承認を付与すると、コントラクトの権限のない実行モデルにより、任意の転送コールを通じてこれらの承認を drain することが誰でも可能になりました。
バッチ実行またはマルチコールスタイルのコントラクトとやり取りするユーザーおよびインテグレーター向け:
-
資金をカストディするように明示的に設計されていないコントラクトには、絶対にERC-20承認を付与しない。
-
汎用的なコール転送コントラクトは、信頼できない実行サーフェスとして扱う。
-
可能な限り、トランザクションごとの承認または承認不要の設計(例:
permit)を優先する。
プロトコルの脆弱性が存在しない場合でも、コントラクトの信頼モデルを誤解すると、重大かつ不可逆的な損失につながる可能性があります。
6. 未知のプロトコルインシデント(2026年2月8日)
概要
2026年2月8日、イーサリアム上の未知のプロトコルが悪用され、約63,000ドルの損失が発生しました。
根本原因は、Gnosis Safeモジュール実行パスにおける検証されていない、攻撃者が制御する入力データでした。SafeModuleとして登録されたユーティリティコントラクト(0xF5E4)は、任意のユーザー提供データをデコードし、直接GnosisSafe.execTransactionFromModule()を呼び出すフラッシュローンコールバックを公開していました。モジュール起源のコールは設計上、署名検証をバイパスするため、攻撃者は任意のSafe承認済みトランザクションを実行し、SafeのAave V3負債を返済し、すべての担保を攻撃者管理アドレスに引き出すことができました。
背景
プロトコルのアーキテクチャは、Aave V3上のレバレッジポジションを管理するGnosis Safeを中心に展開されています。Gnosis Safeはモジュール式実行モデルをサポートしており、指定されたSafeModuleは、オーナー署名を必要とせずにSafeに代わってトランザクションを実行することが許可されています。この設計は、自動化、統合、および高度な戦略をサポートすることを目的としています。
このセットアップでは、コントラクト0xF5E4はGnosis SafeのSafeModuleとして構成されていました。このコントラクトは、フラッシュローンベースのポジション管理をサポートするために設計されたヘルパーユーティリティであると思われます。フラッシュローン実行中に外部流動性プロバイダーによって呼び出されるフラッシュローンコールバック、receiveFlashLoan()を実装しています。
モジュールコールは署名検証をバイパスするため、モジュールロジックの正確性と安全性は極めて重要です。欠陥は事実上、Safeに対する無制限の制御を付与します。
脆弱性分析
SafeModule 0xF5E4は、外部から提供されたuserDataをデコードし、それを直接GnosisSafe.execTransactionFromModule()に呼び出すフラッシュローンコールバックreceiveFlashLoan()を公開しています。0xF5E4はSafeモジュールとして登録されているため、そこから発信されたコールは署名検証をバイパスします。しかし、receiveFlashLoan()は呼び出し元を認証せず、デコードされたパラメータ(ターゲットアドレス、値、コールデータ、または操作タイプなど)を検証しません。その結果、攻撃者は悪意のあるuserDataを提供することで、モジュールがSafeを通じて任意のトランザクションを実行できるようにし、SafeのAave V3負債を返済し、すべての担保を引き出し、利益のためにポジションを drain することを可能にしました。
攻撃分析
-
ステップ1:攻撃者はUniswap V4を通じてフラッシュローンを借入し、資金を
GnosisSafeに転送しました。 -
ステップ2:攻撃者は、実際には資産を借入せず、
recipientを0xF5E4に設定して、悪意のあるuserDataでBalancerのflashLoan()を呼び出しました。 -
ステップ3:
0xF5E4.receiveFlashLoan()内で、コントラクトは攻撃者が提供したuserDataをデコードしました。0xF5E4はSafeモジュールとして登録されているため、署名チェックをバイパスし、userDataに埋め込まれたパラメータで指定されたとおりに任意のコールを実行するためにexecTransactionFromModule()を呼び出しました。 -
ステップ4:この機能を使用して、攻撃者は
GnosisSafeのAave V3での負債を返済し、すべての担保を引き出し、それによって利益を実現しました。
結論
このインシデントは、最終的にはモジュールベースの実行と検証されていない外部入力との安全でない使用によって引き起こされました。SafeModule 0xF5E4は、任意の攻撃者提供のuserDataをexecTransactionFromModule()に転送することで、Gnosis Safeに対する無制限の制御を事実上公開しました。Safeモジュールは設計上署名チェックをバイパスするため、この欠陥はSafeのAave V3ポジションの完全な侵害を可能にしました。
Gnosis Safeモジュールまたは同様の特権実行フレームワークに依存するシステムについて、開発者は以下を行うべきです。
-
フラッシュローン
userDataを含む、すべての外部入力を信頼できないものとして扱い、厳密に検証する。 -
モジュール実行を、定義されたアクション、ターゲット、およびセレクターのセットに制限する。
-
特権実行関数に任意のコールデータを転送する汎用的な「ユーティリティ」モジュールを避ける。
これらのセーフガードの適用を怠ると、単一のヘルパーコントラクトが完全な管理者バックドアに変わる可能性があります。
BlockSecについて
BlockSecは、フルスタックのブロックチェーンセキュリティおよびクリプトコンプライアンスプロバイダーです。私たちは、顧客がコード監査(スマートコントラクト、ブロックチェーン、ウォレットを含む)、リアルタイムでの攻撃傍受、インシデント分析、不正資金追跡、およびAML/CFT義務の遵守を、プロトコルとプラットフォームのライフサイクル全体で実行できるようにする製品とサービスを構築しています。
BlockSecは、著名なカンファレンスで複数のブロックチェーンセキュリティ論文を発表し、DeFiアプリケーションの複数のゼロデイ攻撃を報告し、多数のハッキングを阻止して2000万ドル以上を救済し、数十億ドルの暗号通貨を確保してきました。
-
公式ウェブサイト: https://blocksec.com/
-
公式Twitterアカウント: https://twitter.com/BlockSecTeam



