2023年12月8日、OpenZeppelinは重要なセキュリティ警告を発表しました。ERC-2771標準とMulticallタイプの機能を共同使用する際に、アドレスの置き換えのリスクがあることが判明しました!私はこの脆弱性を深く研究し、自分の発見を共有したいと思います。**攻撃分析**一つの攻撃について考えてみましょう:- 攻撃者:0xFDe0d1575Ed8E06FBf36256bcdfA1F359281455A- 取引:0xecdd111a60debfadc6533de30fb7f55dc5ceed01dfadd30e4a7ebdb416d2f6b6攻撃のスキームは非常にシンプルです:1. 悪意のある者は5 WETHを約3,455,399,346 TIMEに交換しました2. その後、巧妙なパラメータのcalldataを構築し、[Forwarder].executeを呼び出しました。3. この機能はTIMEコントラクトでmulticallを起動し、残りのcalldataはburn() - プール内のトークンを破壊するために使用されました!**これはどう機能するのですか?**この攻撃では、ERC-2771、Multicall、そして慎重に構成されたデータが交わりました。TOKENコントラクトはERC2771Contextを継承しており、ここから最も面白いことが始まります!ERC-2771は仮想のmsg.senderを提供し、トランザクションを第三者に委任することを可能にします。この際、実際のアドレスはcalldataに追加されます。[Forwarder]がコントラクトを呼び出すと、_msgSender()はこれらのデータを確認し、最後の20バイトを"実際の"msg.senderとして切り取ります。Multicallは、1つの呼び出しを複数に変換し、ガスを節約します。彼は呼び出しの配列を受け取り、それらをdeleGatecall()を通じて実行します。そしてここに罠があります!攻撃者はcalldataをシフトさせて、最初の4バイトの新しいデータが関数burn()に対応し、パラメータは膨大なトークンの量になります。0x20の行には、"期待される" msg.senderとなるTIME-ETH流動性プールのアドレスが追加されます!**問題の根本**ERC-2771 [Forwarder]は、multicallでの動作を計画していませんでした!攻撃者は、外部呼び出しmulticallに_parameters _msgSender()を追加しました。multicall内のいくつかの関数もこれらのパラメータを追加し、任意のアドレスからの呼び出しを模倣することを可能にしました!**保護対策**1. 新しいバージョンのOpenZeppelin Multicallは、ERC-2771のコンテキストの長さを保持し、各子呼び出し時にそれを考慮します。2. ThirdWebはさらに進み、すべてのコントラクトがmulticallを呼び出すことを禁止し、[Forwarder]の使用を防ぎました。この脆弱性は、安全なコンポーネントの組み合わせがどのように壊滅的な隙間を生じさせるかの明確な例です!すべての開発者は、常に異なる標準間の相互作用を確認することを忘れないでください。
ERC2771のマルチコールにおける任意のアドレスの置き換え脆弱性の原理分析(SharkTeam)
2023年12月8日、OpenZeppelinは重要なセキュリティ警告を発表しました。ERC-2771標準とMulticallタイプの機能を共同使用する際に、アドレスの置き換えのリスクがあることが判明しました!私はこの脆弱性を深く研究し、自分の発見を共有したいと思います。
攻撃分析
一つの攻撃について考えてみましょう:
攻撃のスキームは非常にシンプルです:
これはどう機能するのですか?
この攻撃では、ERC-2771、Multicall、そして慎重に構成されたデータが交わりました。TOKENコントラクトはERC2771Contextを継承しており、ここから最も面白いことが始まります!
ERC-2771は仮想のmsg.senderを提供し、トランザクションを第三者に委任することを可能にします。この際、実際のアドレスはcalldataに追加されます。[Forwarder]がコントラクトを呼び出すと、_msgSender()はこれらのデータを確認し、最後の20バイトを"実際の"msg.senderとして切り取ります。
Multicallは、1つの呼び出しを複数に変換し、ガスを節約します。彼は呼び出しの配列を受け取り、それらをdeleGatecall()を通じて実行します。
そしてここに罠があります!攻撃者はcalldataをシフトさせて、最初の4バイトの新しいデータが関数burn()に対応し、パラメータは膨大なトークンの量になります。0x20の行には、"期待される" msg.senderとなるTIME-ETH流動性プールのアドレスが追加されます!
問題の根本
ERC-2771 [Forwarder]は、multicallでの動作を計画していませんでした!攻撃者は、外部呼び出しmulticallに_parameters _msgSender()を追加しました。multicall内のいくつかの関数もこれらのパラメータを追加し、任意のアドレスからの呼び出しを模倣することを可能にしました!
保護対策
新しいバージョンのOpenZeppelin Multicallは、ERC-2771のコンテキストの長さを保持し、各子呼び出し時にそれを考慮します。
ThirdWebはさらに進み、すべてのコントラクトがmulticallを呼び出すことを禁止し、[Forwarder]の使用を防ぎました。
この脆弱性は、安全なコンポーネントの組み合わせがどのように壊滅的な隙間を生じさせるかの明確な例です!すべての開発者は、常に異なる標準間の相互作用を確認することを忘れないでください。