コントラクトのエクスプロイトについて

勉強のため以下のXのポストの簡易翻訳を行っています。

今までに、人気のあるオープンソースライブラリに関連するThirdWebのいくつかの契約におけるエクスプロイトについて聞いたことがあるだろう。 このエクスプロイトを理解するのは簡単ではないので、以下に説明する。 飛び込んでみよう:

その背景として、ThirdWebは、一般的なオープンソースライブラリが、そのコントラクトのいくつかに影響を与える問題を起こしたとツイートした。 契約所有者は既存のトークンをロックし、新しい契約に移行しなければならなかった。当時、攻撃による悪用を防ぐため、ライブラリは公開されていなかった。

根本的な原因は、OpenZeppelinのERC2771の実装とその使用方法に関連していることがわかりました。 しかし、この問題はOZの実装に直接関係しているわけではなく、ThirdWeb(TW)のコントラクトでERC2771がどのように使われていたかに関係していることに注意することが重要です。

(最後のコンテキストスライド) ERC2771は、「フォワーダー」契約がユーザーに代わってtxnを提出することを可能にする標準である。このパターンはガスなしTXNに使用され、ユーザーのガス代はガス・スポンサー(フォワーダー)が負担する。 まだ私と一緒?

以下はELI5の説明である: 攻撃者は偽のERC2771トークンを作成し、ThirdWebコントラクトを呼び出す際にトークンの送信者を偽装することができます。 つまり、攻撃者はトークンの所有者になりすまし、トークンを別の場所に移すことができるのです。これにより、すべてのトークンを盗むことができます。

では、より技術的な内訳を説明しよう。 まずERC2771がどのように機能するかを理解する必要がある。トランザクションが信頼されたフォワーダーからサブミットされると、トランザク ションのcalldataに意図されたmsg.senderのアドレスが付加される。

ERC2771Contextを継承した受信コントラクトは、一般的なmsg.senderの代わりに _msgSender関数を使用する。 フォワーダがコントラクトを呼び出すと、_msgSender() は calldata の最後の 20 バイトを見て、意図されたメッセージの送信者を特定します

この悪用は、ThirdWebのコントラクトにマルチコール機能があり、1つのtxn内で複数のtxnを実行できることから発生する。 これはガスを節約するために使用される一般的なパターンですが、通常はERC2771と組み合わせて使用されることはありません。

2コールのマルチコールペイロードがあるとする:[payload_1|payload_2]。 ユーザーがこのペイロードをTrusterフォワーダー経由で送信すると、 ThirdWebコントラクトが受信するペイロードは以下のようになる:[payload_1|payload_2|アドレス]。 最後の 20 バイトが、意図した msg.sender です。
このデータがmulticallで使用されると、まずpayload_1が読み取られる。 ここで、信頼されたフォワーダがこのデータを送信したため、TW契約はERC2771フローを通過し、最後の20バイトのデータを意図されたmsg送信者として受け取ります。 ここで悪用が行われます。

攻撃者はペイロード_1を次のように細工することができる:[real_payload|any_address]のようにすることができる。 ERC2771フローはany_addressを実際のコントラクト呼び出し元として使用するため、攻撃者はトークンの所有者を含め、誰にでもなりすますことができる。

以下は、エクスプロイトを含むコントラクトの例である。https://etherscan.deth.net/token/0xe62be16aa3c50bafb1855b4ded7799d9150bb1a1#code.... ThirdWebは、コントラクトがマルチコールを呼び出さないようにすることで、このエクスプロイトを修正した。 以下、新旧のデリゲート・コールの実装を比較できます:

OpenZeppelinの技術的な詳細については、https://blog.openzeppelin.com/arbitrary-address-spoofing-vulnerability-erc2771context-multicall-public-disclosure。 彼らはさらに包括的なバグフィックスまで行い、EOA以外でもマルチコールを使用できるようにした:

OpenZeppelinのこのエクスプロイトへの対応に大きな賞賛を送りたい。 また、ここ数日このエクスプロイトについて話した@wwwhchungと@0xjustadevの功績も称えたい。

多くの異なるライブラリーが一緒に継承されている場合、バグをキャッチするのは本当に難しい。 そのため、私は依存関係を少なくしてシンプルなコードにすることを説いてきた。 将来、人々がもっと認識するようになることを願っている。

この記事が気に入ったらサポートをしてみませんか?