皆さんは、再帰的な Ethereum 送信エクスプロイトを使用したハッカーによる DAO からの 1 億 5000 万ドルの盗難に関するニュースを聞いたことがあると思います。 この投稿は、これが何であるかを調査する一連の記事の最初のもので、ブロックチェーンを通じて追跡された攻撃者の行動のタイムラインを提供し、技術的なレベルで何が間違っていたかを解体して説明します。最初の投稿では、攻撃者がどのようにして The DAO からすべての資金を盗んだのかに焦点を当てます。 多段階攻撃DAO の脆弱性を悪用することは明らかに簡単ではありませんでした。特定のプログラミング パターンにより、DAO の弱点は明らかになっただけでなく、DAO の作成者によってフレームワークのコードに対する初期の計画された更新で修正されました。皮肉なことに、彼らがブログ記事を書いて勝利を祝っている間に、ハッカーたちは彼らが修正したばかりの同じ機能を狙った脆弱性を準備して悪用し、DAO の資金をすべて浪費していました。 攻撃を全体的に見てみましょう。攻撃者は DAO.sol を分析し、「splitDAO」関数が上記のパターンを再帰的に送信できる脆弱性があることに気付きました。この関数は最終的にユーザーの残高と合計を更新するため、splitDAO を呼び出す前にこの関数を呼び出すことができれば、必要な金額を再帰的に転送できます (コード コメントは XXXX でマークされています。表示するには下にスクロールする必要があります)。 基本的な考え方は次のとおりです。分割を提案します。分割して実行します。 DAO が応答を元に戻す直前に、この関数を呼び出して、元に戻す処理が完了する前に分割を実行します。この関数は残高を更新せずに実行され、上で「攻撃者が複数回実行したい」とマークしたコマンド ラインは複数回実行されます。それは何をするのでしょうか?ソース コードは TokenCreation.sol にあり、親 DAO から子 DAO にトークンを転送します。基本的に、攻撃者はこれを利用して、本来よりも多くのトークンを子 DAO に転送させました。 DAO は転送するトークンの数をどのように決定したのでしょうか?もちろんバランスのとれた配列を使用します。 p.splitData[0]は攻撃者がこの関数を呼び出すたびに同じであるため(これは提案pのプロパティであり、DAOの一般的な状態ではありません)、また、攻撃者は残高配列が更新される前にwithdraw応答からこの関数を呼び出すことができるため、攻撃者はこのコードを取得して攻撃を何度でも実行でき、毎回同じ金額の資金が転送されることになります。 この脆弱性を悪用するために攻撃者が最初に行う必要があるのは、DAO の withdraw 関数を有効にすることです。この機能は、実際に実行すると、決定論的再帰送信の脆弱性にさらされます。これを実現するためにコードで何を行う必要があるかを見てみましょう (DAO.sol より): ハッカーが最初の if ステートメントを false と評価することができれば、脆弱であるとマークされたステートメントが実行されます。このステートメントが実行されると、次のコードが呼び出されます。 リンク先のエクスプロイトの説明に記載されているように、マークされたコマンド ラインが具体的に脆弱なコードであることに注意してください。 このコマンド ラインは、DAO プロトコルからのメッセージを「_recipient」(攻撃者) に送信します。もちろん、「_recipient」には間違った機能が含まれており、攻撃者の最初の呼び出しと同じパラメータを送信して、splitDAO を再度呼び出します。これらすべてが splitDAO の withdrawFor で発生したため、残高を更新する splitDAO のコードは実行されなかったことに注意してください。したがって、Split は子 DAO にさらにトークンを送信し、その後、再度引き出しを要求します。トークンを「_recipient」に再度送信しようとし、残高配列を更新する前に分割 DAO を再度呼び出します。 次のように実行されます:
(補足: Ethereum のガス技術はここでは役に立ちません。Call.value は、send 関数とは異なり、トランザクションに必要なガスをデフォルトで渡します。そのため、攻撃者が支払う限り、コードは実行されます。これは低レベルのエクスプロイトと見なされ、不安定であることを意味します) 上記により、DAO が段階的に空になった経緯を段階的に追跡することができます。 ステップ1: 分割を提案する最初のステップは、前述したように、単に定期的な分割を行うことです。 このステップの攻撃者は、ブロックチェーン上の DAO に「Lonely, so Lonely」という名前の #59 を提案します。 このコマンド ラインは、 ステップ2: メリットを得るこの件については slock.it の以前の投稿で詳しく説明されており、DAO では依然として収益分配は行われていません。 (収益が発生しなかったため)。 概要で述べたように、この重要なコマンド ラインはここで実行する必要があります。 ハッカーが最初のフラグ付きコマンド ラインを実行できる場合、2 番目のフラグ付きコマンド ラインはハッカーが選択したデフォルト関数を実行します (これは、前述したように、splitDAO を返すことと呼ばれます)。 残高機能は Token.sol で定義されており、もちろん次のようになります。 rewardAccount.accumulatedInput() コマンドラインは、ManagedAccount.sol のコードから評価されます。 幸いなことに、accumulatedInput の操作は簡単です。収入アカウントのデフォルト機能を使用するだけです。 それだけでなく、accumulatedInput を減算するロジックはどこにも存在しないため (すべてのトランザクションにわたってアカウントの入力に従います)、攻撃者は Wei を収益アカウントに送信するだけで、初期条件が間違っていると評価されるだけでなく、そのコンポーネント値はすべての呼び出しで同じと評価されます。 balanceOf は残高を参照するため、決して更新されず、splitDAO のコードは実際には実行されないため、paidOut と totalSupply は更新されず、攻撃者は問題なく収益のわずかな分け前を請求できることを覚えておいてください。彼らは収益のこの分け前を請求できるため、デフォルトの関数を実行して、それを splitDAO に返すことができます。 しかし、本当に特典を含める必要があるのでしょうか?もう一度このコマンド ラインを見てみましょう。
支払われない場合、これはエラーとして評価され続け、止まることはありません。なぜ?元のコマンド ラインは同等なので、両辺から paidOut を減算すると、次のようになります。 最初の部分でいくら支払われたか。つまり、小切手は実際には次のようになります。 しかし、amountToBePaid が 0 の場合、DAO はどのような場合でも支払います。これは私にはあまり意味がわかりません。なぜこのようにガスを無駄にするのでしょうか?これが、攻撃者が攻撃を実行するには利益口座残高が必要だと考える人が多い理由だと思いますが、実際にはそれは必要ありません。収益アカウントが空であっても、収益アカウントがいっぱいであっても、攻撃は同じように機能します。 DAO の収益アドレスを見てみましょう。 Slockit ペグの DAO アカウント ファイルでは、このアドレスは ステップ3: 大きな不足ソーシャルメディア上では、攻撃前にビットフィネックスのイーサリアムに300万ドルの不足があり、その不足分が100万ドル近くの利益に相当したという、完全に未確認の主張がいくつかあった。 この攻撃を構築し分析した者は誰であれ、DAO の特定の特性 (特に、どの分割でも元の DAO と同じコードを実行する必要がある) により、攻撃者は悪意のある分割からコインを引き出す前に、子 DAO の作成期間 (27 日間) を待つ必要があることを十分に認識していました。これにより、コミュニティは、ソフトフォークを介して攻撃者のアカウントを凍結するか、ハードフォークを介してプロトコル全体をロールバックすることによって、盗難に対応する時間が与えられます。 テストネットの脆弱性を悪用しようとする金銭目的の攻撃者は、潜在的なロールバックであろうと、基礎となるトークンをショートさせるためのフォークであろうと、利益を確保したいと考えるでしょう。悪意のある分割によって起動されたスマートコントラクトにより、数分以内に価格が急落し、絶好の利益獲得の機会が生まれましたが、攻撃者がこの機会を利用したという証拠はありません。少なくとも、この点に関しては彼らは愚かだったと結論づけることができる。 ステップ 3a: 退出を阻止する (抵抗は無効)攻撃者が考慮しなければならないもう 1 つの可能性は、攻撃者が DAO を枯渇させる前に DAO 分割が発生することです。この方法では、別のユーザーが唯一の管理者として機能するため、攻撃者が DAO の資金にアクセスする可能性はありません。 残念ながら、攻撃者は賢かった。攻撃者の分割提案はすべて彼自身の条件で行われ、DAO 分割の許可を彼が得ていたという証拠がある。この記事の後半で説明しますが、DAO の性質上、ここで説明する DAO 分割は同じ攻撃に対して脆弱です。攻撃者が行う必要があるのは、作成期間後に収益アカウントにいくらかのイーサを送り、新しい DAO からの分割を自ら提案して実行することだけです。新しい DAO 管理者が脆弱性を排除するためにコードを更新する前に彼がこれを実行できれば、彼は自分のものではないイーサを DAO から正常に引き出すことができるでしょう。 ここのタイムラインから、攻撃者が悪意のある分割の開始とほぼ同時にこれらすべてを開始していることがわかります。これは、経済的に実行可能な攻撃というよりも、DAO に対する不必要な屈辱だと私は考えています。DAO を事実上空っぽにした後、テーブルの上に残っているコインを拾い上げようとするこの取り組みは、おそらく、保有者が何もしないように妨害しようとする試みです。多くの人が、そして私も同意見ですが、この攻撃者の動機は利益を得ることではなく、DAO を完全に破壊することだったと結論付けています。真実は誰にも分かりませんが、皆さんもご自身で判断することをお勧めします。 興味深いことに、この攻撃はEmin Gün Sirer氏によって説明された後にブロックチェーン上で発生しましたが、一般の人々はそれ以前には気づいていませんでした。 ステップ4: 分割を実行するこの攻撃の退屈な技術的側面をすべて説明してきたので、次は楽しい部分、つまり悪意のある分割を実行するアクションに移りましょう。分割後に取引を行ったアカウントは 資金を送った子DAOは それは 子 DAO を作成するためにコンストラクタのパラメータを分解すると、マネージャ Johannes Pfeffer は、Medium で、子 DAO に関わるトランザクションの優れたブロックチェーン ベースの再構築を公開しています。彼は素晴らしい仕事をしてくれたので、ブロックチェーンの分析にあまり時間をかけるつもりはありません。この記事に興味のある方は、最初から読み直すことを強くお勧めします。 このシリーズの次の記事では、プロトコル自体の悪意のあるコード(再帰攻撃におけるエクスプロイトの実際の展開を含む)について説明します。出版目的のため、完全な分析は完了していません。 ステップ4a: 分割を展開するこのステップは最初のアップデートのフォローアップであり、攻撃者がどのようにして 30 倍の増幅攻撃 (イーサリアム スタックは 128 ブロックに制限されているため) をアカウントのほぼ無限の流出に変えることができていたのかを不明瞭にしました。 賢明な読者は、スタックを圧倒し、必要以上に悪意のある分割を実行した後でも、コードによって splitDAO が終了した後、ハッカーの残高にはまだ出力がゼロであることに気づいたかもしれません。 では、攻撃者はどのようにしてこの制限を回避するのでしょうか? DAO トークンには送金機能があるため、攻撃者はこれを行う必要がありません。必要なのは、悪意のある関数内から、スタックの一番上にある DAO のヘルパー関数を呼び出すことだけです。 トークンをプロキシ アカウントに転送すると、splitDAO の終了時に元のアカウントの出力がゼロになります (A がすべての資金を B に転送した場合、A のアカウントは splitDAO を通じて出力がゼロになる前に、転送を通じて出力がゼロになることに注意してください)。攻撃者はその後、プロキシ アカウントから元のアカウントに資金を戻し、プロセスを最初からやり直すことができます。 splitDAOのtotalSupplyが失われたとしても、支払いの計算にはp.totalSupply[0]が使用されるため、これは元の提案のプロパティであり、攻撃が発生するまで実現できません。したがって、DAO 内のイーサの量は反復ごとに減少します。攻撃の強さは変わらない可能性があります。 ブロックチェーン上に withdrawRewardFor への悪意のあるプロトコル呼び出しが 2 つ存在するということは、攻撃者のプロキシ アカウントも、攻撃者の元のアカウントと簡単に交換できる、攻撃に使用できる契約であることを示しています。この最適化により、攻撃サイクルごとに 1 つのトレードが節約されますが、不必要であると思われます。 1.1 は脆弱ですか? withdrawRewardFor は脆弱であるため、関数が更新された後も DAO1.1 は同じ攻撃に対して脆弱であるかどうかを尋ねる人もいます。答えは「はい」です。 実際の支払いが行われる前に paidOut が更新されることに注意してください。それで、これは私たちのエクスプロイトにどのような影響を与えるのでしょうか? getRewardFor が 2 回目に呼び出されると、次のコマンド ラインを使用して、splitDAO への悪意のある 2 回目の呼び出しが行われます。 0 になります。呼び出しコストは 攻撃者は悪意のある分割トランザクションを送信するときに大量のガスを支払ったため、再帰攻撃が続行されました。 重要な結論この攻撃にとって、1.1 の感度は興味深いと思います。withdrawRewardFor 自体は脆弱ではなく、withdrawRewardFor のない splitDAO も脆弱ではありませんが、その組み合わせは致命的です。おそらくこれが、テスト中に多くの人がこの脆弱性を何度も見逃した理由です。テスターは一度に 1 つの関数をテストすることに慣れており、安全なサブルーチンを呼び出すと期待どおりに安全に動作すると想定しています。 Ethereum の場合、資金の送信を含む安全な関数であっても、元の関数が再入に対して脆弱になります。それがデフォルトのソリッド ライブラリの関数であるか、自分で頭の中で作り上げた安全関数であるかは関係ありません。状態の更新後に Ethereum コードがすべての機能値が実装されていることを確認するように注意する必要があります。そうでない場合、これらの状態値は再入可能である必要があります。 次に何が起こるでしょうか?ここでは、交差性に関する議論や、イーサリアムと DAO の今後については触れません。この話題はあらゆるソーシャルプラットフォームで予測されており、誰ももうそれについて話したがりません。 一連の発表の次のステップは、DAO 1.0 コードを使用してテストネット上で脆弱性を再現し、そのエクスプロイトの背後にあるコードと攻撃メカニズムを実証することです。誰かが私に勝った場合、シリーズの長さを制限する権利を私は留保しますのでご了承ください。 詳細情報この記事で提供される情報は、攻撃の概要とタイムライン、および分析の出発点を提供することのみを目的としています。 ここで説明したトピックに関連するブロックチェーン データや分析、プロトコル ソース コード、バイナリをお持ちの場合は、phillinuxcom で共有してください。過去 24 時間以内に、クレジットとイベントの完全な再構成を添えてこの投稿に追加させていただきます。 |
<<: 腐敗の終焉: ブロックチェーン技術は透明な政府を構築し、腐敗を排除する
>>: イーサリアムに再びセキュリティ上の脆弱性が発生 - 太陽嵐「ソーラーストーム」がスマートコントラクトのネットワーク全体に影響を及ぼす可能性がある
第0章 はじめに『三体』でヒューゴー賞最優秀小説賞を受賞した劉慈欣氏に祝意を表します。ファンとして、...
Bit.com 初のイベントとして、Bit.com は参加者全員に最大 1,000,000 USDT...
関連市場データによると、本日9時40分現在、XRPの24時間最大上昇率は40.26%、現在の上昇率は...
今週、イーサリアムクラシック(ETC)の価格が急上昇しました。 Huobiの市場データによると、現在...
ビットコインの取引混雑の問題は以前から存在しており、コミュニティではできるだけ早く容量拡張を実現する...
古典的な格言があります。「この混乱に巻き込まれたいなら、あなたが私を殴るか、私があなたを殴るかだ」 ...
40を超える世界的な金融機関のコンソーシアムであるR3CEVは現在、分散型台帳がウォール街の取引を...
2015年12月17日(北京時間)、非営利団体Linux Foundationは最先端のブロックチェ...
ジョージ・キクヴァゼ氏は、ビットコインマイニングおよびブロックチェーン技術企業ビットフューリーの副社...
以下は採掘チュートリアルです1. ETH を購入する (すでにお持ちの場合はスキップしてください)ビ...
制作/ブロックチェーン真実 語り/ラオ・リウ 編集/ヘ・シュロン暗号通貨の世界に入る前、私は絶対的な...
6月28日、ビットコインキャッシュの提唱者であるハビエル・ゴンザレス氏は、ビットコインマイニング議会...
Zerocoin は、複数のデバイスでのマイニングをサポートする MTP アルゴリズムにアップグレー...
11月23日から24日まで、Lieyun.comとLieyun Financeが主催し、VeryH...
クレイジーな解説:中国CITIC銀行(中国)は北京で銀行ブロックチェーンセミナーを開催し、国内の金融...