Solanaネットワークにおける重大なバグの検出と迅速な修正方法

Solanaの脆弱性:rBPFバグによりコントラクト実行パスに影響

Solanaネットワークにおける重大なバグの検出と迅速な修正方法

4月、当社の脆弱性検出システムは、SolanaのrBPF(Solanaの全dAppが稼働している仮想マシン:https://github.com/solana-labs/rbpf)に問題を発見しました。詳細な調査の結果、これはコントラクトの実行パスを誤らせる可能性のあるセキュリティ脆弱性であることが判明しました。このバグをSolanaのセキュリティチームに報告したところ、チームは直ちに脆弱性を確認し修正しました。また、当社のチームには80万米ドル相当のSoLトークンが付与されました。

この脆弱性は、rBPFの新しいバージョン(0.2.26から0.2.27)に存在します。当社が問題を報告した際、メインネットで使用されているバリデーターは影響を受けるバージョンにアップグレードされていませんでした。当社のシステムは、影響を受けるバージョンがマージされる前に問題を検出したため、メインネットのバリデーターはこの脆弱性から免れていました。

以下に、この脆弱性の詳細を説明します。

1. eBPFとrBPF

eBPF(Extended Berkeley Packet Filter)は、当初カーネルでのパケットフィルタリングのために開発されました。eBPFのセキュリティ、効率性、スケーラビリティから、現在ではネットワーキング、トレーシング、プロファイリングなど、さまざまな分野で使用されています(etc)。eBPFの豊富な機能性を考慮し、Solanaはスマートコントラクトの実行エンジンとしてeBPFを採用しています。Solana上でdAppを開発する開発者は、Rustでスマートコントラクトを記述し、コントラクトをeBPFバイトコードにコンパイルします。

Solanaは、Rustで書かれた仮想マシンであるrBPFを使用して、コンパイルされたBPFバイトコードを実行します。しかし、提案された仮想マシン(すなわちrBPF)が堅牢で安全かつ正確であるかは不明です。rBPFにセキュリティ上の問題が存在する場合、rBPFを含むすべてのバリデーターが影響を受け、Solanaネットワーク全体に多大な損失(例:資金の損失)をもたらす可能性があります。

2. 原因

rBPFの実装バグを自動的に特定し、rBPFのコードを定期的にスキャンするツールを開発しました。スキャンプロセス中にrBPF(バージョン0.2.26)で深刻な問題が特定され、コントラクトの実行パスが誤る可能性があります。

具体的には、sdiv命令は符号付き除算命令として使用され、rbpf 0.2.26でデフォルトで有効化された機能として導入されました。sdivは、32ビット(すなわちsdiv32)と64ビット(sdiv64)の両方のオペランドに対する除算をサポートしています。sdiv32命令の場合、計算結果は64ビットのbpfレジスタに格納されます。しかし、sdiv32命令の後の命令が計算結果を64ビットとして読み取った場合、結果が異なる可能性があります。これは、rBPFがJITコンパイル中にsdiv32の計算結果を64ビットの正しい値に拡張しないためです。

例えば、正の数(12)を負の数(-4)でsdiv32で割った場合、正しい結果は32ビットと64ビットの両方で-3になるはずです。以下のコードはその例です。

JITモードとインタプリタモードの両方で実行・トレースした結果、両者の違いを観察することができました。

2.1 インタプリタモード

0 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    29: lddw r5, 0x10000000c
 1 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 000000010000000C, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    31: sdiv32 r5, -4
 2 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, FFFFFFFFFFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    32: jslt r5, 0, lbb_7
 3 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, FFFFFFFFFFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    36: exit

2.2 JITモード

0 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    29: lddw r5, 0x10000000c
 1 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 000000010000000C, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    31: sdiv32 r5, -4
 2 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 00000000FFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    32: jslt r5, 0, lbb_7
 3 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 00000000FFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    33: lddw r0, 0x1
 4 [0000000000000001, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 00000000FFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    35: exit

インタプリタモードでは、レジスタr50xFFFFFFFFFFFFFFFD(32ビットと64ビットモードの両方で-3)に設定されますが、JITモードではr50x00000000FFFFFFFDに設定されます。この場合、64ビット値を受け取るjslt命令では、r5は正の数(0x00000000FFFFFFFD)として認識されるため、実行パスは完全に誤ったものになります。

3. 影響

この実装の誤りは、コントラクトの実行パスの不正確さを招き、深刻な問題を引き起こす可能性があります。

例えば、スマートコントラクトの重要な操作がsdiv32命令の結果に依存している場合、実行結果が不正確になり、攻撃者によって悪用される可能性があります。

この問題はhttps://github.com/solana-labs/rbpf/pull/283で導入されたため、rBPFはバージョン0.2.26から脆弱でした。当社は問題を特定し、2022年4月28日にSolanaのセキュリティチームに報告しました。チームは迅速に対応し、sdiv32命令に符号拡張処理を追加することで数時間で問題を修正しました。修正はhttps://github.com/solana-labs/rbpf/pull/310にあります。当社のタイムリーな検出と報告により、メインネットのバリデーターはこの脆弱性の影響を受けませんでした。

この問題はプロトコルのライブネスバグとして分類され、Solanaから80万米ドルのバグバウンティが付与されました。

タイムライン

  • 2022/04/28: Solanaセキュリティチームに問題を報告
  • 2022/04/29: 脆弱性を修正
  • 2022/05/09: CVE-2022-23066を割り当て
  • 2022/06/01: バグバウンティを付与

BlockSecについて

BlockSecチームは、ブロックチェーンエコシステムのセキュリティに注力し、主要なDeFiプロジェクトと協力して製品の安全性を確保しています。学術界および産業界のトップクラスのセキュリティ研究者と経験豊富な専門家によって設立されたチームです。彼らは、著名なカンファレンスで複数のブロックチェーンセキュリティ論文を発表し、DeFiアプリケーションのゼロデイ攻撃を複数報告し、影響力の大きいセキュリティインシデントの詳細な分析レポートを公開しています。

Twitter: [BlockSecTeam]

Medium: https://blocksecteam.medium.com

Website: https://www.blocksec.com

Sign up for the latest updates