イーサリアム コンスタンチノープル アップグレードの脆弱性の分析

イーサリアム コンスタンチノープル アップグレードの脆弱性の分析
1月15日、ChainSecurityはイーサリアムのコンスタンティノープルハードフォークアップグレードに関連する脆弱性を開示する記事を公開し、このアップグレードにより再突入攻撃が発生すると主張した。これにより、イーサリアムの公式ブログは後に、当初ブロック高7080,000(北京時間1月17日午前頃)に実施される予定だったハードフォークを延期する決定を発表した。以下は ChainSecurity によって公開されたこの脆弱性の詳細です。

イーサリアムの今後のコンスタンティノープル ハードフォーク アップグレードにより、特定の SSTORE 操作のガス コストが安くなります。望ましくない副作用として、 Solidity で記述されたスマート コントラクトでaddress.transfer(...)またはaddress.send(...)を使用すると、再入攻撃が発生する可能性がありますアップグレード前は、これらの関数は再入可能で安全であると考えられていましたが、アップグレード後は安全ではなくなりました。

このコードの何が問題なのでしょうか?

以下は、コンスタンティノープル以前は再入攻撃に対して脆弱ではないが、コンスタンティノープル以降は脆弱になる短いスマート コントラクトです。

攻撃者の契約を含む完全なソースコードは、GitHub でご覧いただけます: https://github.com/ChainSecurity/constantinople-reentrancy

pragma solidity ^0.5.0;

契約 PaymentSharer { マッピング(uint => uint) 分割;マッピング(uint => uint) デポジット;最初にマッピング(uint => 支払先住所)マッピング(uint => 支払可能アドレス) 2番目;

function init(uint id, address payable _first, address payable _second) public { require(first[id] == address(0) && second[id] == address(0));要求(最初の[id] == アドレス(0) && 2番目の[id] == アドレス(0)); first[id] = _first;秒[id] = _秒; }

関数deposit(uint id) public payable { deposits[id] += msg.value; }

関数 updateSplit(uint id, uint split) パブリック { require(split <= 100); splits[id] = 分割; }

function splitFunds(uint id) public { // ここに次の内容があります: // 両当事者がこの分割に同意する署名

// アドレスを分割 payable a = first[id];支払先住所 b = second[id]; uint depo = デポジット[id];預金[id] = 0;

a.transfer(depo * splits[id] / 100); b.transfer(depo * (100 - splits[id]) / 100); } }

最新の脆弱なコードの例。

このコードは予期せぬ形で脆弱であり、安全な金庫共有サービスをシミュレートしていました。両当事者は共同で資金を受け取り、その分配方法を決定し、合意した場合には支払いを受けることができます。攻撃者は、最初のアドレスが攻撃者自身で以下にリストされているアドレス、2 番目のアドレスが攻撃者のアカウントのいずれかであるアドレスのペアを作成します。このアドレスのペアに、攻撃者はいくらかのお金を入金します。

pragma solidity ^0.5.0;

"./PaymentSharer.sol"をインポートします。

契約 攻撃者 { 住所 個人 被害者;支払先所有者の住所;

コンストラクター()パブリック{所有者= msg.sender; }

関数 attack(アドレス a) 外部 { 被害者 = a;支払いシェアー x = 支払いシェアー(a);分割数: 0, 100分割資金(0); }

関数()支払い可能な外部{アドレスx = 被害者;アセンブリ{ mstore(0x80, 0xc3b18fb600000000000000000000000000000000000000000000000000000000000000000000000000000000) pop(call(10000, x, 0, 0x80, 0x44, 0, 0)) } }

関数drain() 外部 { owner.transfer(address(this).balance); } }

攻撃者は最初のアドレスとして契約する

攻撃者は自分のコントラクトで攻撃関数を呼び出し、1 つのトランザクションで次のイベントが展開されます。

1. 攻撃者は、 updateSplitを使用して現在の分割を設定し、将来の更新が安価であることを保証します。これがコンスタンティノープルアップグレードの効果です。攻撃者は、最初のアドレス (コントラクト) がすべての資金を受け取るように分割を設定します。

2. 攻撃者のコントラクトはsplitFunds関数を呼び出し、チェック* を実行し、転送を使用して、このアドレスのペアの預金全体を 1 回の転送でこのコントラクトに送信します。

3. フォールバック機能では、攻撃者は再度分割を更新し、今回はすべての資金を 2 番目のアカウントに割り当てます。

4. splitFundsの実行は継続され、すべての入金も 2 番目の攻撃者のアカウントに転送されます。

つまり、攻撃者はPaymentSharer契約から他の人の ETH を盗んだだけで、今後も盗み続けることができるのです。

なぜ今攻撃できるのか?

コンスタンティノープルのアップグレード前は、各ストレージ操作に少なくとも 5,000 ガスのコストがかかっていました。これは、 transferまたはsendを呼び出すときに送信される 2300 ガス許容量をはるかに超えています。

コンスタンティノープルのアップグレード後、「ダーティ」ストレージ スロットを置き換えるストレージ操作のコストは 200 ガスのみになります。スロットがダーティになるためには、進行中のトランザクション中に変更される必要があります。上記のように、攻撃者は通常、何らかのパブリック関数を呼び出して目的の変数を変更することでこれを実現できます。次に、脆弱なコントラクトに攻撃者のコントラクトを呼び出させます。例: msg.sender.transfer(…) 、攻撃者のコントラクトは 2300 ガスの許容量を使用して脆弱な変数を正常に操作できます。

契約が脆弱であるためには、特定の前提条件を満たす必要があります。

1. transfer/send後に状態変更操作が続く関数 A が存在する必要があります。これは、二次transferや他のスマート コントラクトとのやり取りなど、明らかでない場合があります。

2. 攻撃者がアクセス可能で、(a) 状態を変更し、(b) 機能 A の状態と競合する方法で状態を変更する機能 B が存在する必要があります。

3. 機能 B は 1600 ガス未満で実行する必要があります (2300 ガスの許容量 - 呼び出し用の 700 ガス)

私のスマート コントラクトは脆弱ですか?

契約に脆弱性があるかどうかをテストします。

(a) transferイベント後に何らかの操作があるかどうかを確認します。 (b) これらの操作によって、通常は何らかのストレージ変数を割り当てることによってストレージ状態が変化するかどうかを確認します。トークンtransferメソッドなどの別のコントラクトを呼び出す場合は、どの変数が変更されるかを確認します。リストを作ります。 (c) 管理者以外のユーザーからアクセスされる他のメソッドがこれらの変数のいずれかを使用しているかどうかを確認します。 (d) これらのメソッド自体がストレージ状態を変更しないことを確認します。 (e) メソッドが 2300 ガス未満であることを確認します。SSTORE 操作は 200 ガスのみになる可能性があることに注意してください。

上記のすべてが状況に当てはまる場合、攻撃者が契約を望ましくない状態にしてしまう可能性が高くなります。全体として、これは、チェック - 効果 - 相互作用パターンが非常に重要である理由をもう一度思い出させるものです。

脆弱なスマートコントラクトはありますか?

eveem.org のデータを使用して Ethereum メインチ​​ェーンをスキャンしたところ、脆弱なスマート コントラクトは見つかりませんでした。私たちは、ethsecurity.org ワーキング グループのメンバーと協力して、まだ逆コンパイルされていない複雑なスマート コントラクトにスキャンを拡張しています。特に、信頼できないアカウントへの ETH 転送関数を呼び出して状態を変更することが多い分散型取引所は、脆弱である可能性があります。当社の静的アナライザー https://securify.chainsecurity.com は潜在的な再入攻撃を検出でき、関連するパターンは https://github.com/eth-sri/securify でオープンソース化されています。再入攻撃に関する警告は多くの場合悪用されることはありません。ただし、慎重な分析が必要です。

ありがたい

この新しい攻撃ベクトルについての最初の議論をしてくれた Ralph Pichler 氏に特に感謝します。

シンボリック実行を使用してスマート コントラクトを逆コンパイルする Tomasz Kolinko 氏の作業がなければ、ほとんどの Ethereum スマート コントラクトの高速スキャンを実行することはできませんでした。すべての契約が確保され次第、このプロジェクトをオープンソース化します。

<<:  UEBOT 定量取引リアルタイム 1月16日: ショートポジション |累積損失19%

>>:  米国政府の閉鎖は暗号通貨業界に影響を及ぼしている。カナンクリエイティブの米国でのIPOも失敗するのか?

推薦する

エンタープライズイーサリアムアライアンスは新しいガバナンスモデルを採用する可能性がある

クレイジーなコメント: Enterprise Ethereum Alliance は常に非常に控えめ...

コメディアンのカムの薬物乱用事件は大規模な麻薬密売ネットワークにつながり、犯罪組織は取引に仮想通貨のみを使用している

BlockBeatsによると、上海警察虹口公安局の麻薬対策警察は最近、有名なトークショー俳優カムの背...

ビットコインが期待通りに普及しない場合、半減期後にマイナーはどうなるのでしょうか?

編集者注: 原文は、ビットコインの半減期イベントの調査中にクラーケンがビットコインのインフレメカニズ...

日本の上場企業アクロディア、マイニングファーム建設に6000万元を投資

日経ニュースによると、モバイルソフト開発を手掛ける日本の上場企業アクロディアは、長野県佐久市に仮想通...

地球の塵はまだ落ち着いていない、月は1日で90%以上下落

テラにとってはまだ厳しい一日だ。 15時間前、ド・クォンはUST復旧計画が間もなく発表されるとツイー...

サイドチェーン ソリューションは、ビットコイン開発者の多様化を促進します。それはビットコインの拡大にとってより良い解決策でしょうか?

サイドチェーンについての考え方は変化しているかもしれません。サイドチェーンは歴史的にビットコイン ネ...

FTXは160億ドルを支払う予定です。強気相場後半に向けた「弾薬庫」がまもなくオープンか?

1.はじめに1日のピーク取引量が66億ドルを超え、トークンの時価総額が260億ドルに達し、暗号通貨...

ビットコインネットワークの電力消費量は2020年までにデンマークと同程度になる可能性

Sina Technologyによると、米国のテクノロジーウェブサイトViceは今週、さまざまな理...

UEBOT 定量取引リアルタイム 1月10日: ショートポジション |累積損失7%

序文UEBOTクラウドベースのビットコイン定量裁定ロボットサービスの取引戦略がどのように機能するかを...

トランプ大統領就任初日:国家ビットコイン準備金の設立を優先?

暗号通貨業界は、トランプ次期大統領にビットコイン準備金を積み上げるよう促し、この取り組みに真の政治的...

徐明星さんは利用者らに囲まれ、警察署に連行された。 OKはこう答えた。「彼は無事に出発しました。」

9月11日の報道によると、デジタル通貨取引プラットフォームOKEXは9月5日に再びレバレッジ契約の...

ChainX: ファイルコインはすべてのブロックチェーンプロジェクトのインフラになるかもしれない

最近、Polkadot エコロジカル プロジェクト ChainX がまもなく Filecoin ネッ...

マレーシアは押収したビットコイン採掘機を圧搾ローラーで破壊し、1,000台以上の採掘機が破壊された。

マレーシアでは、盗んだ電力を使って違法に暗号通貨を採掘していたとして1,000台以上のビットコイン採...

KPMGが初めて中国の金融テクノロジー企業トップ50を発表、多くのブロックチェーン企業がリストに

KPMG中国は昨日、中国の主要フィンテック企業50社の初のリストとレポートを発表しました(レポートを...

F2pool BFC (Bitfree Cash) マイニングチュートリアル

Bitcoin Free Cash (略して BFC) は、改良された Cuckoo アルゴリズムに...