Solidityコンパイラの脆弱性分析とセキュリティ対策の実践

Solidityコンパイラの脆弱性解析と対策

コンパイラは現代のコンピュータシステムの基本的な構成要素の一つです。それは、人間が理解しやすく、書きやすい高級プログラミング言語のソースコードを、コンピュータの低レベルCPUまたはバイトコード仮想マシンが実行できる命令コードに変換する特殊なコンピュータプログラムです。

多くの開発者やセキュリティ専門家が通常アプリケーションコードのセキュリティに関心を持つ一方で、コンパイラ自体のセキュリティも無視できません。コンピュータプログラムの一種として、コンパイラにもセキュリティの脆弱性が存在する可能性があり、これらの脆弱性は特定の状況下で深刻な安全リスクをもたらすことがあります。例えば、ブラウザがJavascriptフロントエンドコードをコンパイルおよび解析する際、Javascript解析エンジンの脆弱性により、ユーザーが悪意のあるウェブページにアクセスする際に攻撃者がその脆弱性を利用してリモートコード実行を実現し、最終的に被害者のブラウザや全体のオペレーティングシステムを制御する可能性があります。

Solidityコンパイラも例外ではなく、複数の異なるバージョンにおいてセキュリティ脆弱性が存在します。

Solidity コンパイラの脆弱性

Solidityコンパイラの主な機能は、開発者が記述したスマートコントラクトコードをEthereum仮想マシン(EVM)で実行可能な命令コードに変換することです。これらのEVM命令コードは、トランザクションを通じてEthereumネットワークにパッケージされてアップロードされ、最終的にEVMによって解析され実行されます。

注意すべきは、Solidityコンパイラの脆弱性とEVM自体の脆弱性は異なるということです。EVMの脆弱性は、仮想マシンが命令を実行する際に発生するセキュリティ上の問題を指します。攻撃者が任意のコードをEthereumネットワークにアップロードできるため、これらのコードは最終的に各Ethereum P2Pクライアントプログラムで実行されます。EVMにセキュリティの脆弱性がある場合、Ethereumネットワーク全体に影響を及ぼし、ネットワークのサービス拒否(DoS)を引き起こしたり、攻撃者がブロックチェーン全体を制御する原因となる可能性があります。しかし、EVMは比較的シンプルに設計されており、コアコードはあまり頻繁に更新されないため、このような問題が発生する可能性は低いです。

Solidityコンパイラの脆弱性とは、コンパイラがSolidityコードをEVMコードに変換する際に発生する問題を指します。ブラウザがユーザーのクライアントコンピュータ上でJavaScriptをコンパイルして実行する場合とは異なり、Solidityのコンパイルプロセスはスマートコントラクト開発者のコンピュータ上でのみ行われ、Ethereumネットワーク上では実行されません。したがって、Solidityコンパイラの脆弱性はEthereumネットワーク自体に直接影響を与えることはありません。

Solidity コンパイラの脆弱性の主な危害は、生成された EVM コードがスマートコントラクト開発者の期待と一致しない可能性があることです。Ethereum 上のスマートコントラクトは通常、ユーザーの暗号通貨資産に関与しているため、コンパイラによって引き起こされるスマートコントラクトのバグは、ユーザー資産の損失を引き起こす可能性があり、深刻な結果をもたらす可能性があります。

開発者や契約監査人は、契約コードの論理実装の問題や、再入、整数オーバーフローなどのSolidityレベルのセキュリティ問題に重点を置くかもしれません。しかし、契約ソースコードの論理の監査だけでは、Solidityコンパイラの脆弱性を見つけることは難しいです。特定のコンパイラバージョンと特定のコードパターンを組み合わせて分析する必要があり、そうすることでスマート契約がコンパイラの脆弱性の影響を受けているかどうかを特定できます。

! 【Solidityコンパイラの脆弱性解析と対策】(https://img-cdn.gateio.im/webp-social/moments-7d1e882c0b106528437910218bf21f82.webp)

Solidity コンパイラの脆弱性の例

以下は、具体的な形式、原因および危害を示すいくつかの実際のSolidityコンパイラの脆弱性の例です。

SOL-2016-9 ハイオーダーバイトクリーンストレージ

この脆弱性は、初期のSolidityコンパイラのバージョン(>=0.1.6 <0.4.4)に存在します。

次のコードを考慮してください:

ソリディティ コントラクトC { uint32 a = 0x1234; uint32 b = 0; 関数 f() public { a += 1; } パブリック ビュー run()関数は (uint) { を返します。 bを返す; } }

その中で storage 変数 b は何の変更も受けていないため、run() 関数はデフォルト値 0 を返すべきです。しかし、脆弱性バージョンのコンパイラによって生成されたコードでは、run() は実際には 1 を返します。

一般的な開発者は、単純なコードレビューを通じて上記のコードに存在する問題を見つけることが難しいです。この例は比較的単純で、特に深刻な結果を引き起こさないかもしれませんが、b変数が権限検証や資産記帳などの重要な用途に使用される場合、期待に反するこのような状況は深刻なセキュリティリスクを引き起こす可能性があります。

この問題の根源は、EVMがスタック型仮想マシンを使用していることにあります。スタック内の各要素は32バイトのサイズ(つまりuint256変数のサイズ)です。基盤ストレージの各スロットも32バイトのサイズです。また、Solidity言語はuint32など32バイト未満のさまざまなデータ型をサポートしており、コンパイラはこれらの型の変数を処理する際に、データの正確性を確保するために高位を適切にクリーニング(clean up)する必要があります。上記の状況では、加算が整数オーバーフローを引き起こしたとき、コンパイラは結果の高位を正しくクリーニングせず、その結果、高位の1ビットがストレージに書き込まれ、最終的にa変数の後ろにあるb変数が上書きされ、b変数の値が1に変更されました。

SOL-2022-4 インラインアセンブリメモリ副作用

この脆弱性は >=0.8.13 <0.8.15 バージョンのコンパイラに存在します。次のコードを考慮してください:

ソリディティ コントラクトC { function f() public pure は (uint) { を返します。 アセンブリ { mstore(0, 0x42) } uint x; アセンブリ { x := mload(0) } xを返す; } }

Solidity コンパイラは、Solidity 言語を EVM コードに変換する過程で、単純な翻訳だけではありません。制御フローやデータ分析を深く行い、生成されたコードのサイズを縮小し、実行プロセス中のガス消費を最適化するためのさまざまなコンパイル最適化プロセスを実現します。この種の最適化操作は、さまざまな高級言語のコンパイラで非常に一般的ですが、考慮すべき状況が非常に複雑であるため、バグやセキュリティの脆弱性が発生しやすいです。

上記のコードのバグは、この種の最適化操作に起因しています。コンパイラーは、ある関数内にメモリの0オフセット位置のデータを変更するコードが存在するが、そのデータが後続のどこでも使用されていない場合、メモリ0の変更コードを直接削除できると考え、ガスを節約し、後続のプログラムロジックに影響を与えないと判断します。

この最適化戦略自体には問題はありませんが、具体的なSolidityコンパイラのコード実装において、この種の最適化は単一のアセンブリブロックにのみ適用されます。上記のPoCコードでは、メモリ0への書き込みとアクセスが2つの異なるアセンブリブロックに存在しますが、コンパイラはそれぞれのアセンブリブロックに対してのみ分析最適化を行いました。最初のアセンブリブロックではメモリ0に書き込んだ後に読み取り操作がないため、その書き込み命令は冗長であると判断され、その命令は削除され、バグが発生します。脆弱なバージョンではf()関数が返す値は0ですが、実際には上記のコードが返すべき正しい値は0x42です。

SOL-2022-6 AbiReencodingHeadOverflowWithStaticArrayCleanup

この脆弱性は、バージョン >= 0.5.8 < 0.8.16 のコンパイラに影響します。次のコードを考えてください:

ソリディティ コントラクトC { 関数 f(string[1] calldata a) external pure は (string memory) { を返します。 abi.decode(abi.encode(a)、 (string[1]))[0]; } }

通常、上記のコードが返す a 変数は "aaaa" であるべきです。しかし、脆弱性のあるバージョンでは空の文字列 "" が返されます。

この脆弱性の原因は、Solidity が calldatatype の配列に対して abi.encode 操作を行う際に、誤っていくつかのデータをクリーンアップしたため、隣接する他のデータが変更され、エンコードとデコード後のデータが不一致になったことです。

注意すべきは、Solidityがexternal callとemit eventを行う際に、引数をabi.encodeで暗黙的に処理するため、上記の脆弱性コードが発生する確率が直感的に感じるよりも高いということです。

! 【Solidityコンパイラの脆弱性解析と対策】(https://img-cdn.gateio.im/webp-social/moments-c97428f89ed62d5ad8551cdb2ba30867.webp)

セキュリティの推奨事項

Solidityコンパイラの脆弱性脅威モデルの分析と歴史的な脆弱性の整理を経て、我々は開発者とセキュリティ担当者に以下の提案を行います。

開発者向け###:

  1. より新しいバージョンのSolidityコンパイラを使用してください。新しいバージョンは新たなセキュリティ問題を引き起こす可能性がありますが、既知のセキュリティ問題は通常古いバージョンよりも少ないです。

  2. ユニットテストケースを充実させる。ほとんどのコンパイラレベルのバグは、コードの実行結果が予想と一致しない原因となる。この種の問題はコードレビューで発見するのが難しいが、テスト段階で露呈しやすい。そのため、コードカバレッジを向上させることで、この種の問題を最大限に回避することができる。

  3. インラインアセンブリや多次元配列、複雑な構造体のABIエンコードやデコードなどの複雑な操作はできるだけ避け、明確な要求がない限り、言語の新機能や実験的機能を盲目的に使用して派手さを追求することは避けるべきです。過去の脆弱性の整理によると、大部分の脆弱性はインラインアセンブリやABIエンコーダーなどの操作に関連しています。コンパイラは複雑な言語機能を処理する際にバグが発生しやすくなります。一方、開発者は新機能を使用する際に使用上の誤解が生じやすく、安全性の問題を引き起こす可能性があります。

対安全スタッフ:

  1. Solidity コードのセキュリティ監査を行う際、Solidity コンパイラが引き起こす可能性のあるセキュリティリスクを無視しないでください。Smart Contract Weakness Classification (SWC) の該当するチェック項目は SWC-102: 古いコンパイラバージョンです。

  2. 内部SDL開発プロセスにおいて、開発チームにSolidityコンパイラのバージョンをアップグレードするよう促し、CI/CDプロセスにコンパイラバージョンの自動チェックを導入することを検討できます。

  3. しかし、コンパイラの脆弱性について過度に恐れる必要はありません。ほとんどのコンパイラの脆弱性は特定のコードパターンでのみ発生し、脆弱なバージョンのコンパイラでコンパイルされた契約が必ずしも安全リスクを伴うわけではありません。実際の安全性への影響は、プロジェクトの状況に基づいて具体的に評価する必要があります。

実用リソース

  • Solidity チームが定期的に発表するセキュリティアラート記事
  • Solidity公式リポジトリの定期的に更新されるバグリスト
  • 各バージョンのコンパイラバグリスト。これに基づいて、CI/CDプロセスでコンパイラバージョンの自動チェックを導入し、現在のバージョンに存在するセキュリティ脆弱性を通知することができます。 Code ページ右上隅の三角形の感嘆符のアイコンは、現在のバージョンのコンパイラに存在するセキュリティ脆弱性を示します。

! 【Solidityコンパイラの脆弱性解析と対策】(https://img-cdn.gateio.im/webp-social/moments-84f5083d8748f2aab71fd92671d999a7.webp)

サマリー

この記事では、コンパイラの基本概念から出発し、Solidityコンパイラの脆弱性を紹介し、実際のEthereum開発環境で引き起こす可能性のあるセキュリティリスクを分析します。最後に、開発者やセキュリティ担当者に対していくつかの実用的なセキュリティアドバイスを提供します。これらの脆弱性を理解し、適切な予防策を講じることで、スマートコントラクトのセキュリティをより良く保護し、潜在的な資産損失リスクを減らすことができます。

ETH1.44%
原文表示
このページには第三者のコンテンツが含まれている場合があり、情報提供のみを目的としております(表明・保証をするものではありません)。Gateによる見解の支持や、金融・専門的な助言とみなされるべきものではありません。詳細については免責事項をご覧ください。
  • 報酬
  • 6
  • 共有
コメント
0/400
0xLuckboxvip
· 13時間前
論理的な欠陥は本当に頭痛の種だ 逃げた逃げた
原文表示返信0
LidoStakeAddictvip
· 07-30 09:56
オーバーフローしました コードを修正する必要があります
原文表示返信0
StablecoinArbitrageurvip
· 07-30 09:26
*眼鏡を調整する* うーん... 統計的に言えば、コンパイラリスクはDeFiのTVL計算において深刻に過小評価されている。
原文表示返信0
BoredStakervip
· 07-30 09:24
いつ人間の言葉が話せるようになるの!
原文表示返信0
ArbitrageBotvip
· 07-30 09:24
またコンパイラの罠にハマるの?
原文表示返信0
APY追逐者vip
· 07-30 09:15
狂猎ガス費の時にだけコンパイラの脆弱性を思い出す
原文表示返信0
いつでもどこでも暗号資産取引
qrCode
スキャンしてGateアプリをダウンロード
コミュニティ
日本語
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)