要約
2023年12月5日、Web3開発プラットフォームThirdwebは、事前に構築されたスマートコントラクトのセキュリティ脆弱性を報告しました。この欠陥は、これらのコントラクトを使用してデプロイされたすべてのERC20、ERC721、およびERC1155トークンに影響を与えました。その後の数日間で、脆弱性のあるコントラクトでデプロイされたトークンは、攻撃で徐々に悪用された。
脆弱性分析
ERC-2771
このEIPは、Recipientコントラクトが信頼できるForwarderコントラクトを通して メタトランザクションを受け入れるためのコントラクトレベルのプロトコルを定義する。プロトコルの変更は行われない。受信者コントラクトは、追加の calldata を追加することで、実効的な msg.sender (_msgSender() と呼ぶ) と msg.data (_msgData() と呼ぶ) を送られる。
実際には、OpenZeppelin の実装 ERC2771Context が広く使われている。具体的には、信頼されたフォワーダからの calldata の最後の 20 バイトが _msgSender() として扱われる。一般的なライブラリ利用者にとっては、msg.sender のすべての使用を _msgSender() に置き換えるだけでよいようだ。
言語=javascript function _msgSender() 内部ビューの仮想オーバーライド return (address) { uint256 calldataLength = msg.data.length; uint256 contextSuffixLength = _contextSuffixLength(); if (isTrustedForwarder(msg.sender) && calldataLength >= contextSuffixLength) { { if (isTrustedForwarder(msg.sender) && calldataLength >= contextSuffixLength) return address(bytes20(msg.data[calldataLength - contextSuffixLength:])); を返します。 return super._msgSender(); } }
function _msgData() 内部ビューの仮想オーバーライド return (bytes calldata) { { }. uint256 calldataLength = msg.data.length; uint256 contextSuffixLength = _contextSuffixLength(); if (isTrustedForwarder(msg.sender) && calldataLength >= contextSuffixLength) { { (isTrustedForwarder(msg.sender) && calldataLength >= contextSuffixLength) msg.data[:calldataLength - contextSuffixLength]を返す; を返す。 return super._msgData(); } }
### マルチコール
ユーザーは、複数の通話を1つの通話に統合するためにマルチコールを利用できる。複数の呼のcalldataは、1つの呼のcalldataから抽出される。 実際には、OpenZeppelinの`MulticallUpgradeable`が広く使われている。(バグが修正されました)
function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) { { { result = new bytes[](calldata data)(bytes[] memory results) results = new bytes; for (uint256 i = 0; i < data.length; i++) { 結果[i] = _function[i] = _function[data.length; i++) results[i] = _functionDelegateCall(address(this), data[i]); } return results; }
### ERC-2771 + マルチコール
この問題は、これら2つのコンポーネント(ERC-2771とMulticall)の間で、calldataがどのようにパックされ、どのようにアンパックされるかに矛盾があるために発生する。ERC-2771に従って、信頼されたフォワーダはメッセージデータと送信者情報を一緒にパックすべきである。その後、コントラクトは `_msgData()` と `_msgSender()` を使用して、それぞれメッセージデータと送信者情報をアンパックする。
しかし、このマルチコール関数は ERC-2771 がデータをパックする方法とは互換性がありません。もし正しく実装されていれば、 `Multicall` は `_msgSender()` を使って送信者情報をアンパックし、それを各メッセージの呼び出しデータに追加して、それ以降の呼び出しで正しくアンパックできるようにする必要があります。しかし、実際の実装ではこのステップを見逃している。
一方、ERC-2771に従ったコントラクトは `_msgData()` と `_msgSender()` を使ってメッセージデータと送信者情報をアンパックしようとします。しかし、calldataに送信者情報が付加されていない場合、送信者情報は`_msgData()`の最後の20バイトとしてアンパックされ、攻撃者はこれを制御することができます。これにより、攻撃者は、仕様で設定された期待に反して、任意の送信者情報で悪意のあるロジックを実行する、操作されたcalldataを構築することができる。
## 攻撃分析
攻撃トランザクションの一例](https://app.blocksec.com/explorer/tx/eth/0xecdd111a60debfadc6533de30fb7f55dc5ceed01dfadd30e4a7ebdb416d2f6b6)を例にとって説明する。
* ステップ1: 5つの$WETHを3,455,399,346 $TIMEと交換する。
* ステップ2: 慎重に細工されたデータで信頼されたフォワーダーを呼び出す。マルチコールで解析された後、バーン関数が `_msgSender()`としてUniswapプールで呼び出される。プールの$TIME残高が減少する。
* ステップ3: プールを同期し、$TIMEの価格を引き上げる。
* ステップ4:3,455,399,346ドルのTIMEを94ドルのWETHと交換する。
ステップ2が攻撃の鍵である。攻撃者はForwarder.executeを呼び出してデータを転送する:

しかし、それは長さ1のbytes[]として解析され、その後、コントラクトを呼び出すためのデータとして使われる。

## ハイライト&レッスン
DeFi空間では、サードパーティ・ライブラリのセキュリティに注意を払うことが極めて重要である。残念ながら、これらのライブラリは時に予期せぬ秘密の方法で相互に作用し、契約のセキュリティに脅威をもたらすことがある。このことは、このような相互作用から生じる可能性のある脆弱性を軽減するために、徹底的な監査と監視を行うことの重要性を浮き彫りにしている。
## このシリーズの他の記事を読む
- リードイン:2023年の "すごい "セキュリティ事件トップ10](https://blocksec.com/blog/top-ten-awesome-security-incidents-in-2023)
- フラッシュボット・リレーの脆弱性を悪用したMEVボットの収穫](https://blocksec.com/blog/harvesting-mev-bots-by-exploiting-vulnerabilities-in-flashbots-relay)
- 2位:オイラー・ファイナンス事件:2023年最大のハッキング](https://blocksec.com/blog/euler-finance-incident-the-largest-hack-of-2023)
- 3位:KyberSwap事件:非常に微妙な計算で丸め誤差を巧みに悪用](https://blocksec.com/blog/kyberswap-incident-masterful-exploitation-of-rounding-errors-with-exceedingly-subtle-calculations)
- 4位:Curve事件:コンパイラのエラーにより、無害なソースコードから欠陥のあるバイトコードが生成される](https://blocksec.com/blog/curve-incident-compiler-error-produces-faulty-bytecode-from-innocent-source-code)
- [#5:カモノハシファイナンス:3度の攻撃を運良く生き延びる](https://blocksec.com/blog/5-platypus-finance-surviving-three-attacks-with-a-stroke-of-luck)
- 6位:百済事件:脆弱なフォーク・プロトコルにおける精密関連エクスプロイトの波を触媒する](https://blocksec.com/blog/6-hundred-finance-incident-catalyzing-the-wave-of-precision-related-exploits-in-vulnerable-forked-protocols)
- 7位:ParaSpace事件:業界で最も重大な攻撃を阻止するための時間との戦い](https://blocksec.com/blog/paraspace-incident-a-race-against-time-to-thwart-the-industrys-most-critical-attack-yet)
- 8位:SushiSwap事件:不手際な救助活動が模倣攻撃の連鎖を招く](https://blocksec.com/blog/8-sushi-swap-incident-a-clumsy-rescue-attempt-leads-to-a-series-of-copycat-attacks)
- [#9:MEVボット0xd61492:独創的なエクスプロイトで捕食者から捕食者へ](https://blocksec.com/blog/9-mev-bot-0xd61492-from-predator-to-prey-in-an-ingenious-exploit)



