注意! イーサリアムのSはセキュリティの略です。 パート1.ブロックチェーンのこと







この記事では、Solidity言語のスマートコントラクトに固有の典型的な脆弱性、攻撃、問題領域、およびEthereumプラットフォーム全体に特化したシリーズを開始します。 最初の部分では、これについて説明します。









スマート契約で分散型取引所を実装するのが難しいのはなぜですか



免責事項: ZeroNights 2017のコンテストの分析では、前走攻撃について既に説明しました。したがって、それを読んだ人は次のポイントに直接進むことができます。







フロントランニングという用語はかなり前に登場し、待機状態(保留中)のトランザクションに関するクローズド情報を所有しているため、市場で操作される可能性を意味します。 詐欺師は、大規模な購入が行われていることを知っている場合、交渉の対象を安値ですぐに買い取ることができるため、自分自身の利益を保証できます。







暗号通貨、特にイーサリアムでは、すべてのトランザクションは最初に未確認のプール(保留中のプールまたはmempoolまたはバックログ)に配置され、マイナーがそこから取得してブロックに追加するまで待機します。 ただし、このような情報を非常に狭い範囲の人々が利用できる従来の交換とは異なり、すべてのネットワークメンバーはイーサリアムの保留中のプールを見ることができます。 そして、新しいトランザクションがブロックに落ちるまでの平均時間は約14秒であるため、攻撃者は市場の動作を分析し、この動作を考慮した独自のトランザクションを送信するのに十分な時間を持っています。 最後に、 攻撃者は、トランザクションが最初に処理されることをどのようにして確認できますか? 答えは取引手数料の額にあります-金額が大きいほど、取引はより早くブロックに入ります。 ただし、イーサリアムでは、手数料の概念は通常よりも少し複雑で、次のように計算されます。









=gasPricegas







ここで、ガスはEVMの特定の燃料単位であり、スマートコントラクトを実行してデータをブロックチェーンに保存するときに消費されます。 したがって、実際には、攻撃者はガスの単位(gasPrice)の価格を操作することにより、取引が取引所にとって最初であることを確認できます。 ここここに、スマートコントラクトに対してこのような攻撃を行う例があります。

この攻撃の緩和策として、スマートコントラクトはtx.gasprice



トランザクションtx.gasprice



分析できtx.gasprice



。 ただし、これは問題に対する完全な解決策ではありません。これは、鉱夫が実際にトランザクションをgasPriceの降順でソートする義務を負わないためです。これは単なる経済的インセンティブです。 突然、より重要な安定した勝利オプションが現れた場合、誰が鉱夫が何をするかを知っています:)







これを何らかの形で防ぐために、暗号化を使用できます。たとえば、最初に目的のアクション(購入または販売)のハッシュをトークンの数で送信します。 そして、次のブロックではすでにデータ自体を送信しています。 スキームにも欠点がないわけではありませんが、少なくともより複雑です。2倍のトランザクションを実行する必要があります。







乱数を生成する方法



その設計におけるイーサリアムは決定論的なメカニズムであるため、内部でエントロピーを取得することは非常に困難です。 ただし、Solidityのすべての開発者が内部構造に精通しているわけではありませんが、自分自身の前に言語の構文の説明だけを見て、他のプログラミング言語で行った方法でそれを適用しようとします。

したがって、エントロピーを取得できない場合:









例外はblock.blockhash(uint blockNumber)



関数で、ブロックハッシュをその番号で返します。 ただし、次の2つのことを念頭に置いて適用する必要があります。









ブロックハッシュの不適切な使用とそれらの悪用の例は、 ここここにあります







もう1つのオプションは、 RANDAOが使用するコミット/公開スキームです。 最初のフェーズでは、M個のブロックに対して、N人の参加者が乱数を推測し、そこからハッシュを送信して、スマートコントラクトにいくらかの入金をします。 第2フェーズでは、参加者は隠し番号をスマートコントラクトに送信し、スマートコントラクトはハッシュから番号を取得してスマートコントラクトをチェックします。 全員が番号を送信した後、契約はそれらをPRNGのシードとして使用します。 参加者が指定された時間に番号を送信しなかった場合、参加者は彼が行ったデポジットを失い、ラウンドはキャンセルされます(残りはデポジットを受け取ります)。 このスキームの欠点は明らかです-DOSの影響を受けやすいため、乱数が絶えず必要になった場合、そのようなスキームは純粋な形ではほとんど適していません。 Vitalikのように、RANDAO自身が提案し、またはそれに基づいて独自の方法を考案したため、このスキームの追加ルールを確認する価値があります。 またはアイデアをブロックハッシュとコミット/公開スキームと組み合わせることができます。







もう1つの注目すべきオプションはSignidiceです。 このスキームは参加者が少ない場合に適しているため、ルーレットゲームの例として考えます。 そのため、2人の参加者がいます-カジノとプレイヤー、そしてゲームのロジックを実装するスマートコントラクト。 準備段階で、カジノは秘密鍵と公開鍵のペアを生成し、公開スマート契約を送信します。 この準備が終わったら、プレイできます。 行こう:









現時点でこのスキームを採用および適用できない最大の欠点は、イーサリアムの署名アルゴリズムがECDSAであることです。 そして、あなたがそれを使用する場合、カジノは常にチートする機会があります。 アルゴリズムに同意します 。3番目のステップで、ランダムなkが選択されます。 このパラメーターは最終的な署名に直接影響し、同じkを使用することはできません。そうしないと、2つの署名があるため、カジノの秘密鍵を復元できます(同じ理由でkを開くことはできません)。 したがって、カジノは勝つための署名を受け取るまでkを変更できます。 そのようなカジノの例を次に示します。

さらに(前の問題は別として)、参加者が同じ番号を推測した場合の対処方法の問題を解決する必要があります。 カジノが署名に同じパラメーター(kを含む)を使用する場合、以前のパラメーターと同じになります。つまり、ランダムではありません。 したがって、予測される数字の再利用またはラウンドごとの新しいキーペアの生成を禁止する必要があります。







Signidiceの「トンネルの終わりの光」は、モジュラーテイク操作の追加に関するEIP-198です。 これにより、RSAの署名検証を実装できます。 RSAを使用する場合、カジノの不正行為は失敗します。







実際、乱数を取得する問題を解決するためのアプローチ、オフチェーン( Oraclizeエントロピーを取得するためのオプション、およびささやきの実験は船外に残っています。







証明ネットワークを無効にする方法



このブロックでは、スマートコントラクトについては触れませんが、許可されたブロックチェーンの1つの機能、バリデーターは常に既知であると考えます。 例として、権限証明コンセンサスを持つネットワーク。 Proof-of-Authorityは、Proof-of-workコンセンサスを持つネットワークの特殊なケースであり、選択されたノード(バリデーター)のみがマイニングできます。 そのようなネットワークの顕著な例は、開発者KovanとRinkbeyのテストネットワークです。 このようなコンセンサスは、主にスパム攻撃を回避するために考案されました。 (GPUを使用しているため)電力に利点がある悪意のあるマイナーが、ネットワークの他の部分よりも速く新しいブロックを抽出すると、多数のエーテルを手に入れます。 通常のネットワーク参加者は、自分でエーテルを取得することはできませんが、以前は善意の鉱夫によって補充されていた「タップ」を排出します。 これはすべて、エーテルの不足のために新しい開発者がネットワークを使用できないという事実につながります。 まだエーテルを持っている人にとっては、そのようなネットワークでの通常の操作も不可能です。 マイナーは、意味のない、しかし高価なトランザクションでネットワークを散らかすことができます。その結果、通常のネットワーク参加者をトランザクションブロックに追加することが難しくなり、時間がかかります。







そのため、選択したバリデータを使用した証明のアプローチは、テストネットワークだけでなく、許可されたネットワークにも適用できます。 たとえば、 PoAネットワークは、合法的に割り当てられたメンバーが検証者である公的にアクセス可能なネットワークです。 PoAは、これらのDOS攻撃のネットワークを解放しますか? はい、いいえ。







インターネットのレベルでは、マイナーがリッスンするポート30303に大量のトラフィックを生成する機会がまだあります。 そして、それにより、ネットワークの他の部分からアクセスできなくなります。 さらに明らかなのは、バリデーターがなく、誰もブロックを抽出せず、トランザクションが蓄積され、ネットワークが立っているということです。 しかし、ネットワーク内のマイナーを計算する方法は? 結局のところ、彼は他のネットワークとまったく同じクライアントを使用しています。







アルゴリズムは実際には単純です。









 curl --data '{"method":"parity_netPeers","params":[],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST localhost:8545 -s | jq '.result.peers[]' | jq '.network.remoteAddress' | cut -d "\"" -f 2 | cut -d ":" -f 1
      
      





25を超える場合は、たとえばiptablesを使用して既知のIPへの接続を強制的に切断し、すべてを収集する必要があります。







さらに、必要なのは、最初のブロックがどのIPから到着するかを追跡することだけです。 これらのIPはマイナーです。







今のところすべてです。 次のパートでは、スマートコントラクトで発生する可能性のある問題に直接進みます。








All Articles