
一部の旧型Qualcommチップセットのハイパーバイザーファームウェアにおけるセキュリティ問題
CVE-2022-22063 は、一部の古い Qualcomm チップセットのハイパーバイザーファームウェアにおけるセキュリティ上の問題です。保護されていないハードウェアコンポーネント(「ブートリマッパー」)を悪用すると、改変されたオペレーティングシステムからハイパーバイザーへの完全な読み取り/書き込みアクセスを取得できます(権限昇格)。影響を受けるプラットフォームでは、特定のファームウェアバージョンに関する知識(アドレスや変数など)が不要なため、この問題の悪用は簡単です。
注記: Qualcomm は顧客に修正を提供しましたが(アップデートをリリースする十分な時間がありました)、影響を受けるデバイスの多くはかなり古く、ベンダーから修正を受け取れない場合があります。この問題は、改変された、または侵害されたオペレーティングシステムから(別のセキュリティ問題を利用して)のみ悪用可能です。ファームウェアに脆弱性があっても、オペレーティングシステムを最新かつ安全な状態に保つことで十分な場合があります。
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:Hこの問題は [Qualcomm's December 2022 Security Bulletin] にも掲載されました。
この問題は、影響を受ける対象で実行されているハードウェアとソフトウェアの組み合わせに依存します:
hyp パーティション内の ELF イメージ)。APCS_BOOT_START_ADDR_NSEC と呼ばれるハードウェアレジスタを使用して設定可能)。これはハイパーバイザーによって保護されておらず、したがって特権レベルの低いオペレーティングシステムカーネル(例:Linux)からアクセス可能です。影響を受けるハードウェアを搭載している可能性が高いチップセットは他にもいくつかあります(例:MSM8909 や MSM8953)が、それらには侵害される可能性のある別個のハイパーバイザーファームウェアがありません。
権限昇格: すでに侵害されたオペレーティングシステムカーネル(例:Linux)があれば、この問題によりハイパーバイザーレベル(ARM では EL1 -> EL2)への権限昇格が簡単に可能になります。ハイパーバイザーが管理するすべてのメモリを読み取りまたは書き込みできます。これにより、ハイパーバイザーが管理する異なるセキュリティドメインや仮想マシン(存在する場合、設定に依存)の分離が破られます。
(関連情報:[An introduction to Access Control on Qualcomm Snapdragon Platforms])
セキュアブート: 市場に出回っているほとんどの Qualcomm デバイスは、ファームウェアの不正な変更を防ぐためにセキュアブートを利用しています。ファームウェアは暗号署名され、ブートチェーンによって検証されます。この問題により、改変されたオペレーティングシステムから(公式にサポートされている「ブートローダーアンロック」または別のエクスプロイトを介して)、ロードされたハイパーバイザーファームウェアを実行時に変更したり、完全に置き換えたりすることが可能です。
(関連情報:[Qualcomm Secure Boot and Image Authentication Technical Overview (v1.0)] および (v2.0))
注記: この問題は元々、Qualcomm Snapdragon 410 (MSM8916) プラットフォームで発見されました。以下の説明の一部は MSM8916 に固有の場合があります。例えば:
ただし、一般的な概念は影響を受けるすべてのプラットフォームに同様に適用されます。
ARMv8-A 64 ビットアーキテクチャは、4 つの特権レベル(「例外レベル」、EL)を定義しています。アプリケーション、オペレーティングシステムカーネル、ハイパーバイザーに通常使用される別々のレベルがあります:
CPU は例外の発生中にレベル間を切り替えます。例えば、割り込みが到来した場合などです。また、ハイパーバイザーコール (hvc) などの特別な命令を使用して、一部のレベル間を切り替えることもできます。
(関連情報:[AArch64 Exception model])
ハイパーバイザーは、それぞれ独立したオペレーティングシステムカーネルを持つ 1 つまたは複数の仮想マシンをホストできます。各仮想マシンには、ステージ2変換 を使用して独自のメモリビューを提供できます。仮想マシンからのすべてのメモリアクセスは、2 つの変換ステージを通過します:最初のステージは(仮想)オペレーティングシステムが管理し、2 番目のステージはハイパーバイザーが管理します。ハイパーバイザーや他の仮想マシンが使用するメモリは、変換テーブルから省略することで隠すことができます。
(関連情報:[AArch64 virtualization], [AArch64 memory management])
Qualcomm のハイパーバイザーファームウェアは EL2 で実行され、ステージ2変換を使用して、EL1 で実行中のメインのオペレーティングシステムカーネル(通常は Linux)からハイパーバイザーメモリへのアクセスを禁止しています。この構成では、ステージ2変換は主にアドレス変換なしのメモリ保護に使用されることに注意してください。メインのオペレーティングシステムは、メモリマップド入出力 (MMIO) 空間内のほとんどのハードウェアコンポーネント(例:SD コントローラーやカメラサブシステム)に直接アクセスできます。ハイパーバイザー/EL2 (hyp) とセキュアモニター/EL3 (tz の一部) に属するメモリへのアクセスは制限されています:
ブートリマッパー は仮想化とは関係ありません:CPU コアの起動初期に必要です。このハードウェアプラットフォームでは、CPU コアは常にアドレス 0x0 から実行を開始します。ブートリマッパーは、CPU の周囲に組み込まれた追加のハードウェアコンポーネントであり、最初の 64 または 128 KiB (0x00000 - 0x20000) を設定可能なメモリ領域にリマップします。
デフォルトでは、ブートリマッパーはブート ROM(デバイス起動時に最初に実行されるコード)を指しています。その後、マッピングが変更され、他の CPU コアが RAM にロードされた EL3 ファームウェア(tz の一部)で直ちに実行を開始するようになります:
CPU がアクセスするアドレス(tz 内)は、2 つの異なる物理アドレスを使用してアクセス可能になることに注目してください:RAM 内の実際のアドレス (0x8650xxxx) と、ブートリマッパーを使用したリマップ後のアドレス (0x0000xxxx) です。
実際には、ブートリマッパーには 2 つの別々のインスタンスがあります:
APCS_BOOT_START_ADDR_SEC (= 0x0b010004) を使用して設定できますが、セキュア状態でのみ設定可能です。APCS_BOOT_START_ADDR_NSEC (= 0x0b010008) を使用して設定可能です。両方のブートリマッパーインスタンスは、リマップ領域のベースアドレスと 2 つの設定ビットを含むメモリレジスタを使用して設定できます:REMAP_EN はリマップを有効にし、BOOT_128KB_EN は 64 KiB だけでなく最初の 128 KiB をリマップします。
(関連情報:[Qualcomm Snapdragon 410E Technical Reference Manual rev. D]、85 ページと 116 ページ)
前の 2 つのセクションの知識を使えば、基本的なアイデアは単純です:ブートリマッパーを使用して、ハイパーバイザーのメモリ保護(ステージ2変換)をバイパスします。
ブートリマッパーは CPU 起動時にのみ機能するわけではありません。いつでも使用でき、リマップ領域への完全な読み取り/書き込み/実行アクセスを許可します。また、Qualcomm のハイパーバイザーは、影響を受けるデバイス上でオペレーティングシステムがブートリマッパーの非セキュアインスタンスを設定およびアクセスすることを防いでいないようです(ステージ2変換によって保護されていません)。したがって、この問題は次のように簡単に悪用できます:
hyp)を指すように設定し、リマップ領域は動的に(ブロック単位で)シフトでき、ブートリマッパーで利用可能な 64/128 KiB よりも大きなメモリ領域にアクセスできます。また、これを使用してハイパーバイザーのメモリ保護を完全に無効にすることも可能です(概念実証 を参照)。
注記: 同じエクスプロイトはセキュアワールドファームウェア (tz) には機能しません。ブートリマッパーはステージ2変換をバイパスできますが、DRAM 内の tz メモリ領域は、ブートリマッパーを通過した後のアクセスを遮断する追加のハードウェアコンポーネント(CPU の外部)によって保護されているようです:
tz メモリ領域はおそらくセキュア状態でのみアクセス可能です。このエクスプロイトでバイパスできるのはハイパーバイザーのメモリ保護のみであり、ハードウェアの他のセキュリティメカニズムは引き続き有効です。
ブートリマッパーを使用すると、ファームウェアバージョンに関する知識なしに、元のハイパーバイザーファームウェアを実行時に完全に無効化して置き換えることができます。特に、変更される可能性のある変数や関数のメモリアドレスを取得するためにリバースエンジニアリングを使用する必要はありません。ハイパーバイザーファームウェアのおおよそのメモリ領域を知るだけで十分です。例えば、オープンソースの Linux コード内のメモリ予約から、またはハイパーバイザーファームウェアバイナリ(内部ストレージの hyp パーティションにあります)の ELF ヘッダーを読むことによって得られます。
一般的なアイデアは次のとおりです:
hvc) を実行して、オペレーティングシステムからハイパーバイザーへ(EL1 から EL2 へ)切り替えます。これを実装するコードは長くはありませんが、低レベルの AArch64 アセンブリと CPU キャッシュの慎重な操作が必要です。しかし、主な疑問はまだ未解決です:コードを特定のハイパーバイザーファームウェアバージョンに依存させずに、シェルコードを正確にどこに書き込むべきでしょうか?
ハイパーバイザーコール中(一般に任意の例外中)は、CPU の実行は特別なメモリアドレス、つまり 例外ベクター に強制的に移されます。例外ベクターは、現在の例外レベルまたは下位の例外レベルから発生するさまざまな種類の例外を処理するコードを含む、より大きな ベクターテーブル の一部です:
各ボックスは、32 個のアセンブリ命令を格納できる例外ベクターを表しています。この領域では不十分なため、通常は追加コードを置くためのより広い領域へジャンプする分岐命令が含まれます。
オフセットは、各例外レベルのベクターテーブルのベースアドレスを定義する ベクターベースアドレスレジスタ (VBAR) を基準にしています。ハイパーバイザーはベースアドレスを VBAR_EL2 CPU レジスタに書き込みます。
ハイパーバイザーコールは、下位の例外レベル(EL1 で実行中のオペレーティングシステムカーネルから EL2 のハイパーバイザーへ)から行われる同期例外です。したがって、オペレーティングシステムカーネルが 32 ビットモードで実行されている場合、CPU は VBAR_EL2+0x600 にジャンプし、64 ビットモードでは VBAR_EL2+0x400 にジャンプします。ブートリマッパーを使用してこのアドレスにカスタムコードを書き込み、ハイパーバイザーコールを行うと、CPU はシェルコードの実行を開始します。
残念ながら、VBAR_EL2 は EL1 で実行中のオペレーティングシステムカーネルからは読み取れません。読み取れるのはハイパーバイザー(EL2)自身またはそれ以上の特権レベルだけです。それでも、この知識があれば、ブルートフォースでエントリアドレスを推測するのははるかに簡単になります:ベクターテーブルのベースアドレスは、そのサイズ (0x800 = 2 KiB) の倍数にアラインされている必要があります。つまり、128 KiB の領域内では 64 か所、1 MiB の領域内では 512 か所しか存在しません:
赤いボックスは、ハイパーバイザーコール中に CPU がジャンプする可能性のあるすべての場所を示しています。これらのすべてにシェルコードを書き込めば、特定のファームウェアバージョン(実際にはベクターテーブルが特定の 1 つのアドレスにあります)に依存しないアプローチを維持できます。
これはさらに改善できます:ブートリマッパーは読み取りと書き込みの両方を許可するため、メモリ位置から読み取った既存のコード/データに基づくヒューリスティックを追加することも可能です。そこには有効な AArch64 (A64) 命令と、おそらく NOP や分岐命令などの繰り返される埋め草バイトが含まれているはずです。(各例外ベクターの 32 命令分の領域は、より広い領域を持つ適切な関数へ分岐する方が簡単なため、部分的にしか使用されないことがよくあります。)
このリポジトリに含まれる概念実証コードは、Snapdragon 410 (MSM8916/APQ8016) プラットフォーム向けの Qualcomm のオープンソース Little Kernel (LK) ブートローダー を改変したもので、元々は DragonBoard 410c 開発ボード でのテストを意図していました。これらはすべて簡便さのために選ばれました。この問題は、他のオペレーティングシステム(Linux など)、他の影響を受けるプラットフォーム、さらにはセキュアブートを有効にしたデバイスでも、オペレーティングシステムカーネル内でカスタムコードを実行する方法があれば悪用可能です。
このコードは、上記のアプローチを実装して、実行中のハイパーバイザーを完全に無効化し、それを別のバージョンに置き換えます。新しい「ハイパーバイザー」は仮想マシンをサポートしませんが、単純なハイパーバイザーコールを使用して 生命、宇宙、そして万物についての究極の疑問の答え を返すことができます:``` $ fastboot oem CVE-2022-22063 < waiting for any device > (bootloader) Hypervisor, what is the Answer to The Ultimate Question of (bootloader) Life, the Universe and Everything? (bootloader) Old hypervisor returned answer: -2 (bootloader) Old non-secure boot remapper base address: 0x100000 (bootloader) Setting boot remapper to hypervisor memory (0x86400000) (bootloader) Using boot remapper to copy shell code to hypervisor memory (bootloader) Copying to all possible vector tables (starting at 0x600) (bootloader) Calling shell code to disable running hypervisor (bootloader) Found old EL2 vector base address at 0x86404000 (bootloader) Copying new code directly to hypervisor memory (0x86400000) (bootloader) Hypervisor, what is the Answer to The Ultimate Question of (bootloader) Life, the Universe and Everything? (bootloader) New hypervisor returned answer: 42 OKAY [ 0.015s] Finished. Total time: 0.015s
### テスト
概念実証コードは、以下のようにビルドしてテストできます。```shell
$ git clone https://git.codelinaro.org/clo/la/kernel/lk.git -b caf_migration/LA.BR.1.2.9.1_rb1.5
$ cp CVE-2022-22063.c lk/platform/msm8916/
$ git apply LK.diff
# Build LK for msm8916 and flash it to device
$ fastboot oem CVE-2022-22063
...
ただし、この構成は DragonBoard 410c 開発ボード や、プライマリブートローダーを簡単に(かつ安全に)置き換えられるセキュアブート非対応のその他のデバイスにのみ適しています。このリポジトリのコードは主に参考用として提供されており、簡単に使用・テストできるようにはなっていません。
将来は、このコードを新しいバージョンの lk2nd に統合する予定です。lk2nd は、プライマリブートローダーを置き換えることなく、さまざまなデバイスでより簡単にテストできます。
Qualcomm によると、この問題はステージ2変換を使用してブートリマッパー領域へのアクセスを禁止することで修正されました。ブートリマッパー構成(APCS_BOOT_START_ADDR_NSEC レジスタ)には引き続きアクセスできますが、両方のメモリ領域がブロックされるようになりました:
もう1つの可能な修正方法は、ハイパーバイザー内で APCS_BOOT_START_ADDR_NSEC レジスタを保護することです。この場合、オペレーティングシステムがブートリマッパーを他のメモリ領域に再設定する方法がないため、リマップされた領域へのアクセスは引き続き許可できます。
Qualcomm によると、この問題は通常の自動化ツールが使用できなかったため、対応が特に困難でした。同社が受け取る問題のほとんどはソフトウェアの問題であり、ソースコードを確認することで影響を受けるデバイスを特定できます。しかし、この問題では、ハードウェアとソフトウェアの両方を手動で確認する必要がありました(プラットフォームに問題のあるレジスタが存在するかどうか、ハイパーバイザーに脆弱性があるかどうか)。残念ながら、自動化を使用しなかったことで、この問題がセキュリティ情報に自動的にスケジュールされることもありませんでした。2回目のエンバーゴ延長は、顧客にセキュリティ問題を認識させ、デバイスにパッチを適用する時間を与えるために要請されました。同社は、今後の報告でこのような問題を避けるためにプロセスの改善に取り組んでいます。
CVE-2022-22063 レポートと図 © 2022 Stephan Gerhold は クリエイティブ・コモンズ 表示 - 継承 4.0 国際 (CC BY-SA 4.0) の下でライセンスされています。
概念実証コード (CVE-2022-22063.c) は MIT ライセンスの下で提供されます。