記事「未確認送信エラーのライブイーサリアム契約のスキャン」の続き。 パート1」
ほぼ1年前(Ethereumが「フロンティア」リリースであった)、人気のあるEtherPot宝くじ契約[9]も同じエラーに悩まされていました。 BTCRelayの以前のバージョンもこのエラーを示しました[7] 。 以前のセキュリティ監査でハザードが検出されましたが、誤った修正が最初に適用されました[8] 。
ライブブロックハインの未送信エラー検出
これらのエラーはどれほど一般的ですか? 彼らは警告を聞いていますか? ベストプラクティスが適用されていますか? イーサリアムブロックチェーンデータと、etherscrape.comにあるSolidityコードリポジトリを分析することにより、これらの質問に経験的に答えます。 これを行うために、ブロックチェーンコントラクトをチェックし、ヒューリスティックを使用して最も効果的な保護方法の1つが使用されているかどうかをチェックする簡単なプログラム分析ツールを開発しています。 リスト2は、Ethereumのドキュメントで推奨されている最初のセキュリティ手法を示しています。これは、 sendの戻り値をチェックし、例外をスローする必要があります。 このメソッドの使用を検出するには、大まかな近似を使用します。sendの戻り値が無視されるかどうかを確認するだけです。
リスト4は、テストメッセージを送信してコールスタックがいっぱいかどうかを直接チェックする、UMDマニュアルで推奨されている2番目のセキュリティ手法を示しています。 この手法を発見するために、大まかな近似を再度使用します。sendコマンドに加えてメッセージが送信されているかどうかを確認するだけです。
これらのヒューリスティックインジケータが存在しない場合、ベストプラクティスの推奨事項のいずれも守られていないと判断します。 コンパイルされたEVMバイトコードとの単純なパターンマッチングを使用して、これらのヒューリスティックを実装します。 これを行う方法の詳細については、付録[12]を参照してください。
脆弱な契約はいくつありますか?
まず、SolidityソースコードのEtherscrapeリポジトリでヒューリスティックを確認してみましょう。 2016年3月20日現在、Etherscrapeリレーには361個のSolidity契約プログラムが含まれており、そのうち56個には送信ステートメントが含まれていました。 これらの契約プログラムの中で、ほとんど(少なくとも56のうち36)が防衛的なプログラミング方法を使用しないと想定しています。
契約で保護技術が使用されていない場合でも、実際の脆弱性がある場合とない場合があります。 Solidity契約を手動でチェックして、脆弱性を確認しました。 私たちの目的では、 sendコマンドが機能しない場合でも状態が変化する可能性がある場合、コントラクトは脆弱であると考えます(リスト5の脆弱なコードを見ていきます)。 脆弱性の大部分、これらの契約の36のうち32が存在することを確認しました。
同様に、我々の発見的手法は、防御的プログラミングの正しい適用を保証するものではありません。 たとえば、分散型のオープンソースのクラウドファンディングDAppであるWeiFundを考えてみましょう。 このコントラクトには、 返金()とペイアウト()の 2つの機能があります。 以下は返金からの抜粋です。
function refund(uint _campaignID, uint contributionID) public { ... receiver.send(donation.amountContributed); donation.refunded = true; ... if(c.config != address(0)) WeiFundConfig(c.config).refund(_campaignID, donation.contributor, donation.amountContributed); }
このコードでは、メッセージがWeiFundConfig(c.config)に送信され、特定の条件下でのみ払い戻しメソッドが呼び出されます。 c.configがヌル値の場合、コントラクトは実際にコールスタック攻撃に対して脆弱です。 *をチェックすると、ヒューリスティックテストに合格したSolidityプログラムはどれも、推奨される最良のコールスタックテストプラクティスを直接適用しませんでした。 *
次に、生きているブロックチェーンイーサリアムの契約草案に注意を向けます。 2016年3月20日付の画像(タイムスタンプ:1184243)を確認しました。 このスナップショットには、合計13645個のブロックチェーンが含まれており、これらは明らかにSolidityコンパイラによって生成され、そのうち1618(11.8%)のみがsendコマンドを含んでいます 。
これらのうち、大多数は防御的なプログラミング手法を使用していないようです。
TheDAOの再帰的な人種問題はどうですか? 最近の最もエキサイティングなスマートコントラクトであるTheDAO [11]は、完全に独立したエラーに悩まされています。これは、「再利用しても安全」ではないということです[13] 。 これは、以前のセキュリティチェック[6]でも予想されていた別の(接続されているが、明確な)種類の安全でないプログラミングですが、以前と同様、おそらく多くの契約が今日安全ではありません。 今後の作業では、このようなエラーも検出できるツールを作成しました。
どこでうまくいかなかったのですか?
スマートコントラクトでのプログラミングは、少なくともまだまだ完全にシンプルになるとは考えていません。 しかし、イーサリアムエコシステムの開発中にずっと前に説明されたという事実にもかかわらず、この特定の形式のエラーが非常に広範囲に及ぶことは驚くべきことです。
2015年のレポート[6]は、イーサリアム開発者にこの勧告を行いました。
現在、ドキュメントに示されているプログラミング例は、安全な契約を作成し、ガスメカニズムの問題を解決するためのベストプラクティスを広めるには不十分です。 C ++入門チュートリアルはしばしばスキップします
読みやすさのエラーチェック。これにより、多数のセキュリティエラーが発生しました。 イーサリアムの例は最高の習慣を教えるべきです。 推奨事項:セキュリティ契約の注意深いプログラミングのさらに多くの例を提供してください。」
この質問に対する公式の答えは1つだけです。これは、前述のSolidityの公式ドキュメントに警告を追加することです[3]。以下に繰り返します。「 sendを使用すると、危険があります 。 1024(これは常に発信者が呼び出すことができます)、また受信者がガソリンを使い果たした場合も失敗するため、安全なブロードキャストを確保するために、 sendの戻り値を常に確認するか、さらに良い:パターンを使用します 受取人がお金を引き出す」
この観察では、問題を文書化するには不十分であると考えています。 不完全な緩和のみを提供し、危険の1つのバージョンのみを説明し、読者にその程度について誤解を招く可能性があります。
更新:
Solidityのドキュメントの不備も、Peter Wesenesによって詳しく説明されました。 [16]
さらに、警告はしばしば見過ごされているようです。 したがって、追加の予防措置が必要であると考えています。
Etherscrapeはどのように役立ちますか?
静的分析ツールを使用すると、この記事で説明したような粗雑なものであっても、スマートコントラクトの品質を向上させることができると考えています。彼女が準備ができたら。 これにより、エラーが発生する可能性のある場所を強調表示することで、スマートコントラクトのコードを簡単に表示できます。 このようなスマートコントラクトのユーザー(TheDAOやそのオファーの潜在的な投資家など)は、資金を入金する前に健全性チェックなどのツールを簡単に使用できると想定しています。 技術に詳しくない投資家でも、開発者がコードに記載された問題にどのように反応したかを説明する責任を負うことができます。
また、Etherscrapeは、パブリックブロックチェーンを分析し、このエラーの発生率を制御することで役立ちます。これは、たとえば、静的分析ツールの研究開発に充てる金額を決定するのに役立ちます。 さらに、 solcなどのコンパイラーはそのような分析を統合し、エラーが発生する可能性がある場合にプログラマーに警告を提供できます。
推奨読書
- [1] 安全なスマート契約の作成に向けた段階的な手順
- [2] EthereumおよびSerpentのUMDプログラマーズガイド(セクション5.14)
- [3] 公式Ethereum Solidityドキュメント
- [4] エーテルの王:死後の調査
- [5] 契約セキュリティに関するSwende
- [6] イーサリアムの最小権限監査
- [7] BTCリレー監査1
- [8] BTCリレー監査2
- [9] EtherPotセキュリティバグレポート
- [10] リエントラント契約
- [11] DAO(分散自治組織)
- [12] 付録A:ブロックチェーンの分析方法の詳細
- [13] DAOの一時的なモラトリアムの要請
- [14] 付録B:脆弱性のある契約
- [15] 付録C:脆弱なブロックチェーン契約
- [16] イーサリアム悲嘆
ウォレット:投函/投球は危険です