DAO攻撃者の足跡を追う

DAO攻撃者の足跡を追う

この投稿は、DAO エクスプロイトの原理とタイムラインを説明した前回のブログ投稿の続編です: http://hackingdistributed.com/2016/06/18/analysis-of-the-dao-exploit/ (http://www.8btc.com/thedao-exploit-analysis)

二次侵略

上記では、現在メディアや研究者の注目も集めているDAOのwithdrawRewardFor脆弱性の再帰送信に主に焦点を当てました。上記では、攻撃者が 30 倍に増幅し、無制限に繰り返すことができる攻撃について説明しました。

当初、実装の詳細は重要ではないと考えていましたが、Joey Krug と Martin Köppelmann は、これらの詳細がいかに重要であるかを示すために懸命に取り組んでくれました。マーティン氏が指摘したように、確かに 2 つの別個のエクスプロイトが、3 つ目のより強力な脆弱性につながります。

  1. splitDAO では、withdrawRewardFor 関数からの再帰攻撃により、アクセスできるはずの DAO トークンの 30 倍を引き出すことができますが、実行できるのは 1 回だけです。

  2. エントリーすることは可能ですが、これは非再帰攻撃であり、splitDAO では withdrawRewardFor 転送を通じて、分割ごとにトークンを 2 倍にすることができます。

  3. (1)と(2)の組み合わせで、権利のあるトークンの30倍を譲渡することができ、何度でもエントリーすることができます。

攻撃者は 3 番目の方法を実装しました。これについては前に説明しましたが、2 番目の方法を見てみましょう。 1 番目と 3 番目の脆弱性が修正された契約を作成します。ループエントリの脆弱性のない完璧なコントラクトである withdrawRewardFor を見てみましょう。前回の投稿を思い出してください。withdrawRewardFor の脆弱性により、DAO 1.1 の splitDAO が再入可能になりましたが、この脆弱性は修正されたかもしれませんが、この関数の最初の行にはまだ問題が残っています。

関数 withdrawRewardFor(address _account) noEther 内部は (bool _success) を返します {
if ((balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply < paidOut[_account])
投げる;

uint 報酬 =
(balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply – paidOut[_account];

報酬 = rewardAccount.balance < 報酬 ? rewardAccount.balance: 報酬;

paidOut[_account] += 報酬;
if (!rewardAccount.payOut(_account, reward))
投げる;

true を返します。
}

報酬アカウントに残高がなく、ユーザーに支払われる金額が 0 の場合でも、payOut の呼び出しは実行され、受信者のコントラクト内の任意のコードが呼び出されることに注意してください。

関数payOut(address _recipient, uint _amount)は(bool)を返します{
if (msg.sender != 所有者 || msg.value > 0 || (payOwnerOnly && _recipient != 所有者))
投げる;
if (_recipient.call.value(_amount)()) { // 脆弱

}

getRewardFor が初めて実行されると、有効な報酬が支払われます。 2 回目の支払いは 0 になり、3 回目は依然として 0、4 回目は依然として同じです... また、ユーザーは splitDAO に戻り、受け取るべき金額を 30 倍に増やすこともできます。

DAO 1.1 で修正された withdrawRewardFor でも、再入脆弱性が残っていることに注意してください。この再入性は、関数を 2 回目 (3 回目、4 回目) に実行すると 0 が支払われるため、報酬アカウントの残高を脅かすことはありません。ただし、再入性攻撃に対しては依然として脆弱です。

DAO 1.2 でこれを修正すると、withdrawRewardFor 関数が再入可能性に対して脆弱にならないように完璧に記述されます。この関数は次のようになります。

関数 withdrawRewardFor(address _account) noEther 内部は (bool _success) を返します {
((balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply <= paidOut[_account]) の場合
false を返します。 // すべてのsplitDAO呼び出しが失敗しないようにする、直交変更

赤く塗られた部分のみが変更され、単に < が ≤ に変更されました。なぜ?この関数を2回目に実行すると、paidOut[_account]の値は左側の式の値と等しくなります。再突入がトリガーされる前にコードが設定されます:

uint 報酬 =
(balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply – paidOut[_account];
paidOut[_account] += 報酬;

したがって、これは、古典的なアンチモデルのベスト プラクティスである再入可能性の脆弱性がない、DAO 1.1 の withdrawFor の外観です。このコードはシンプルで読みやすいです。

このようにすると、前回の記事で説明した splitDAO の無限増幅の弱点は存在せず、攻撃者はこれを行いません。残高がゼロの場合、payOut 呼び出しは実行されないため、この関数を繰り返し実行しても意味がありません。

しかし、Joey Krug 氏が指摘しているように、これによって、withdrawRewardFunction を使用して DAO 1.2 をドレインする同じエクスプロイトの使用を防ぐことはできません。重要なのは、新しいケースで withdrawRewardFor を使用して任意のコードを 1 回呼び出すことができ、1 回で十分であるということです。

関数自体がこの脆弱性を増幅します。報酬を引き出すときに DAO の転送関数を呼び出すと、トークンが子 DAO に転送された後に残高がゼロになり、トークンは新しいアカウントに存在することになります。コードの詳細な説明は前回の記事にあります。主に splitDAO 関数と transfer 関数に関するもので、どちらも同じ残高配列を非アトミックに変更します。

したがって、プロセスに非アトミックに影響を与えるロジックは、任意のコントラクトを実行するための呼び出しによってプロセスが中断された場合に脆弱性を生み出し、攻撃を受ける可能性があります。したがって、「再入不可能な関数を記述する」ことに加えて、外部コントラクトを呼び出さないように注意してください。そうしないと、プログラム フローやステータスを予測できなくなります。

このエクスプロイトには興味深い点がいくつかあります。まず、遅いです。基本的に、トークンを移動するたびにトークンが 2 倍になります。しかし、これは攻撃の成功には影響しません。攻撃は十分に速く、速いからといって誰も止めることはできません。

2 番目に、私たちが修正した DAO 1.1 コードでは、報酬アカウントの残高が必要であったため、再入脆弱性が解消されました。 rewardAccount.accumulatedInput() の戻り値が 0 の場合、ユーザーには支払いが行われず、変更された関数は常に false を返すため、悪意のある可能性のあるコードは実行されません。公開された DAO1.1 コードでは、withdrawRewardFor の脆弱性がまだ存在しており、withdrawRewardFor を実行するために報酬アカウントに残高がなくてもかまいません。

実際には、これらはどれも重要ではなく、意図的であろうとなかろうとボーナス口座に資金が投入される可能性があります。つまり、攻撃者は毎回報酬の一部を転送することができ、DAO 1.2 が修正された後でも withdrawRewardFor 関数を使用して再度侵入することができます。

Solidityのデメリット

私が挙げた最初の脆弱性が存在しなかったら、コミュニティは間違いなく 2 番目の脆弱性を見逃していたでしょう。 1 つ目は反モデルの例であり、この時点ではこれを防止しようとします。2 つ目は、より微妙な反モデルの例です。元の関数の再入性はなく、元のコントラクトの再入性のみです。

要約すると:

  1. Solidity の呼び出し構造を使用して外部コントラクトを呼び出す場合、または変更したコントラクトに外部で呼び出される関数がある場合、コントラクトが外部呼び出しを実行すると、その後の状態を予測することはできません。

  2. これは、DAO エクスプロイトの現状では既知のプログラミング手法ではありません。 Solidity の呼び出しドキュメントを参照できます: https://github.com/ethereum/wiki/wiki/Solidity-Features#generic-call-method この構造を使用すると、多くのセキュリティ上の脆弱性が無視され、開発者が誤ったセキュリティ認識を持つことになります。

  3. 上で示唆したように、コントラクト内から外部コントラクト コードを呼び出すために Solidity の呼び出し構造を使用しないでください。避けられるのであれば、決してそうしないでください。これを行わないと、プログラムの流れに関するすべての保証が失われることに注意してください。

私にとって、上記は、DAO 契約自体の欠陥や脆弱性以上のものを意味します。つまり、技術的には、これらは Ethereum 仮想マシン自体によって設計された機能ですが、Solidity によって契約にセキュリティ上の脆弱性が生じ、コミュニティだけでなく言語の設計者からも無視されました。

私の意見では、この脆弱性の責任の 50% は Solidity 言語の設計者に帰属するはずであり、これにより、このようなケースに対する修正措置が改善される可能性があります。契約コードの書き方が下手なことだけを責めることに同意しません。契約コードがこの言語ドキュメントに完全に従って記述されたとしても、このような脆弱性は残ります。

奇妙な助けの要請

この記事を書いているときに、DAO 報酬アカウントに関する興味深い点に偶然出会いました。攻撃者はなぜ報酬を集めたのか、そして誰がそのお金を報酬アカウントに移したのか? DAO 攻撃中に withdrawRewardFor 関数が実行され続けたのはなぜですか?

DAOの報酬アドレスを見てみましょう。 DAO の会計情報は Slockit から取得されます。アドレスは、0xd2e16a20dd7b1ae54fb0312209784478d069c7b0 (https://github.com/slockit/DAO/wiki/Understanding-the-DAO-accounting) です。トランザクション記録を見てみましょう: https://etherscan.io/txsInternal?a=0xd2e16a20dd7b1ae54fb0312209784478d069c7b0&&zero=true&p=220 攻撃者の悪意のあるコントラクトである 0xf835a0247b0063c04ef22006ebe57c5f11977cc4 と 0xc0ee9db1a9e07ca63e4ff0d5fb6f86bf68d47b89 に 0.00000002 イーサが 200 ページ転送されていることがわかります。

しかし、これらのコインがどこから来たのか、最後のページのアカウント取引記録を見てください。DAO の作成の最後に、アドレス 0xe76563eb8413ede9b4a1a3c1f3280a95c4b60a33 から 0.001 イーサリアムを送信する単一の金銭取引記録です。

同じアドレスは後にThe DAOに投資し、DigixDAOトークンを保有しています。

私の理論では、彼はおそらく DAO クラウドセールに投資したいと思ってプログラムで購入しようとして失敗した初心者だったと思います。しかし、メインの DAO アドレスが間違っている可能性があるのでしょうか?これらは daohub.org のホームページにありますが、報酬アドレスは DAO wiki の片隅に表示されます。では、なぜこのアドレスに送金するのでしょうか? DAO アーキテクチャを試してみて、どう反応するか見てみようと思っている人ですか?

さらに興味深いのは、このアカウントを検索すると、イーサリアム フォーラムに、イーサを送信するための Javascript API に関するヘルプを求める投稿が見つかります。このアカウントはこのスレッドを投稿してから一度もログインしていません。これは彼らの唯一の投稿です https://forum.ethereum.org/discussion/7109/web3-eth-gettransaction-returned-null。

これはブロックチェーンの歴史を垣間見る興味深い機会となるかもしれないが、その答えは永遠に分からないだろう。あなたがこのアカウントの所有者であれば、当時何を考えていたか知りたいです。

攻撃者は一人ではない

前回の投稿を見ると、私が攻撃者の経路を非常に早く分析できたのは、以前に私自身がそのような攻撃を構築していたからだということがわかります。

1週間前、Emin Gün Sirer からメールを受け取りました。

2016年6月11日土曜日 17:42:37 Emin G Sirer 著 <> 皆さん、こんにちは。
DAO を空にする方法が分かりました。

私はDAOのこの脆弱性を分析するのに数時間を費やしました。週末、私は V1.1 のいくつかの潜在的な脆弱性のトラブルシューティングに数時間を費やし、Sirer から次のような返信がありました。

2016-06-12 13:34:09 Emin G Sirer <> さんが書きました 奇妙なことに、私はこの潜在的な問題に最初に気づいた人の一人でした…
私は依然としてsplitDAOは脆弱であると考えています。この関数が呼び出されるまでbalances[]はクリアされないため、引き出しモードに違反します。したがって、rewardTokens を移動することで DAO を複数回分割できた可能性があると思います。これは、DAO.sol の 640 行目から 666 行目で発生します。私が間違っているでしょうか?
いずれにせよ、これは確かに静的に分析可能な脆弱性です。 Andrew Miller にこの問題の静的分析を行ったかどうか尋ねてみます。

そこで私は数時間かけて splitDAO を分析し、再帰送信の脆弱性を引き起こす可能性はないと判断しました。私の簡単な答えは、それはありそうにないということです。タイミングの問題を挙げましたが、splitDAO 内からでも TokenProxy の作成からも再帰送信をトリガーすることは不可能です。私はいくつかの可能なエクスプロイトを実演し、それから自分の仕事に戻りました。

Sirer 氏のチームにはこの問題を調査している他のメンバーもいましたが、さらに深く調査してみると、この脆弱性を誘発する方法を知っているのは攻撃者だけではないということが興味深いことになってきました。

DAO の失敗は避けられなかった。私はこの一連の記事を、証明しようとするのではなく好奇心から書いているのですが、世間の監視の力について少し希望が持てましたし、私たちはそれにあまり驚いてはいけないと思っています。

短い不在

私のこの一連の投稿を読んでいただきありがとうございます。少しでも参考になれば幸いです。
仕事の都合上、週末は theDAO をフォローしません。私のTwitterで関連ニュースを見ることができます https://twitter.com/phildaian

やるべきことはまだたくさんあります。ハッカーのトークンがどこに行き着いたのか、そしてその理由も含め、攻撃の完全なブロックチェーン像を再構築する必要があります。ハッカーが現在攻撃をテストしているかどうかを確認するには、公開テスト ネットワークを検索する必要があります。ドキュメント化と分析のために、元の Solidity コードを慎重に逆コンパイルして再構築する必要があります。

私たちは経験から学び、ベスト プラクティスを使用する必要があります (いくつかのアイデア: これらのコントラクトを徐々にスケールアップし、Solidity での呼び出し構造の使用を停止します)。コミュニティとして、私たちは前進する道筋を描き、分岐するかどうかを決定する必要があります。

最後に、スマート コントラクト テクノロジーへの関心が現在かつてないほど高まっていることをお伝えしたいと思います。これは、先週よりも強力で、より指導的で、より組織的で、より原則的なコミュニティを紹介する絶好の機会です。

このエクスプロイトの開発とテストに数え切れないほどの時間を費やしてくれたこのハッカーに感謝したいと思います。脱帽です、今回は私たちに勝ちましたね。次回はそんなに幸運ではないでしょうね。


<<:  Bloq CEO ジェフ・ガージック氏との独占インタビュー: 貪欲さが The DAO の悲劇の原因

>>:  スイス政府はブロックチェーン企業に対する規制を緩和し、金融技術改革を推進すると予想される

推薦する

ロシア、10億ルーブルの偽造事件を摘発、容疑者は偽造紙幣を仮想通貨で販売

BlockBeatsによると、ロシア当局はダークウェブ上で大量の偽造紙幣を暗号通貨と交換に販売してい...

ワンダグループが中国ブロックチェーン技術・産業発展フォーラムに参加

9月8日、万達グループは工業情報化部が主催するブロックチェーン技術と産業発展フォーラムに副議長団とし...

デジタル通貨の「楽園」はどこにあるのでしょうか?この国は世界のビットコイン取引の60%を占めている

2007年から2008年にかけての世界的金融危機は世界経済に深刻なダメージを与えました。消費者の資産...

資産運用大手のVanEckが米国SECにイーサリアムETF申請書を提出、米国初のイーサリアムETFとなる可能性も!

金曜日の規制当局への公開書類によると、資産運用大手のヴァンエックは、米証券取引委員会(SEC)に「ヴ...

[初心者からマスターまで採掘] [初心者ガイド] 採掘産業のエコシステム - 採掘機械サービス

採掘初心者からマスターまで(XI)はじめに - マイニングの基礎 ASICマイニングマシンの動作環境...

Matrixportの強気相場での投資配分方法——トレンド志英を選択

Matrixportは2019年にシンガポールで設立され、Bitmain、IDG Capital、L...

【市場分析】ビットコインの拡大は再び物議を醸し、通貨価格は引き続き上昇する可能性

1. 市場動向ビットコインの現在の価格は4,350元前後で、日足ラインは大きなダブルトップパターンを...

従業員はビットコインで給料を受け取ることができますか?この場所の市長は公然と楽観的です!マスク氏は逃したことを後悔している

分散化の波の中で、ビットコインはますます多くの支持を集めています。個人投資家とウォール街の中央集権的...

韓国の新韓銀行がブロックチェーンベンチャーに200万ドルの投資に参加

コメント:アジアは、ブロックチェーン技術の発展動向において、依然として比較的保守的な立場にあります。...

FCH(FREECASH)は2月21日にHuobi取引所に上場される予定

Tigerユーザー様: Huobiは、2020年2月21日14:00(UTC+8)にFCH/USDT...

ビットコインの価格は8,000ドル、仮想通貨のマイニングはもはや利益を生まないと報告

「ビットコインは現在、基本的に1ビットコインの採掘コストの損益分岐点で取引されている」とファンドスト...

顧延喜氏:米国のビットコイン採掘産業は今後数年間で急速に成長するだろう

2020年は、特に第4四半期において、米国市場における暗号デジタル金融の発展が加速した年です。 Pa...

これは強気相場の前に参加できる最後のチャンスでしょうか?

最近、強気相場が始まる前に投資を始​​める最後のチャンスについて語るブロガーを多く見かけます。前回の...

ビットコインは6,000ドルまで下落?アナリストは「非常に可能性が高い」と述べている

ビットコイン弱気派は、市場を席巻した最近の楽観論とほぼ同じ速さで猛烈な勢いで戻ってきた。最近、ゴール...

【Filecoin】Drand: Filecoin のランダム性の源

ブロックチェーンのセキュリティ保証の 1 つは、秘密鍵、ブロック生成権、チャレンジ シードなどのさま...