
CVE-2019-5700
残念ながら、この脆弱性に流行りの巧妙な名前はありません。このバグは非常に簡単に悪用できます。実際、私はこれをかなり長い間寝かせていましたが、最初に考えていたよりも多くのデバイスに影響するかもしれないと気づきました。
このバグは、Androidブートイメージを起動するNvidia Tegra t114-t210 SoCに影響します。ただし、1つ重要な区別があります。
t114ベースのデバイスは、TOS(TLK - Nvidiaのセキュアモニタ)もロードする統合ブートローダーを搭載しているため、はるかに深刻な影響を受けます。つまり、ブートローダーはすでにセキュアコンテキストで実行されています...
t124+デバイスでは、Nvidiaは現在、脆弱なブートローダーが実行される前にTOSをロードする初期段階のブートローダーとしてnvtbootを使用しています。その脆弱なブートローダーがカーネルをロードして実行します。つまり、非セキュアコンテキストで実行していることになります。
Androidブートイメージヘッダー(v1 - Android 9より前)を見てみましょう:
struct boot_img_hdr
{
uint8_t magic[BOOT_MAGIC_SIZE];
uint32_t kernel_size; /* size in bytes */
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t second_size; /* size in bytes */
uint32_t second_addr; /* physical load addr */
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
uint32_t unused;
uint32_t os_version;
uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */
uint8_t cmdline[BOOT_ARGS_SIZE];
uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
};
kernelやramdiskといったおなじみのイメージのフィールドがあります:
uint32_t kernel_size; /* size in bytes */
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
そして時にはtags(デバイスツリーやATAGSによく使われます)
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
'second'フィールドはどうでしょうか?
uint32_t second_size; /* size in bytes */
uint32_t second_addr; /* physical load addr */
実際に本番デバイスで使用されているのを個人的に見たことはありませんが、'second'イメージはセカンドステージブートローダーや、ロードが必要な追加イメージに使用できると理解しています。私の研究経験では、他のOEMのほとんどのブートローダーは、使用されないためこのフィールドを無視するか、サイズとアドレスにサニティチェックを適用します。
Nvidiaのブートローダーは、カーネル、ramdisk、dtbに対して実際にサニティチェックを適用します。これらはすべてハードコードされたロードアドレスを持っているため、ヘッダーのロードアドレスは無視されます。しかし、Nvidiaはおそらくこのほとんど忘れられたイメージのことを忘れていたようです...アドレスやサイズのサニティチェックなしに任意にロードしています。その通りです。任意のイメージを、任意のサイズで、アクセス可能な任意のメモリアドレスにロードできます(t114ではすべて、t124+では非セキュアメモリ)。
つまり、メモリ内のブートローダーを自由にパッチして、自分の目的に合わせることができます。署名検証をスキップしたい場合(すべてのイメージをロードした直後に行われます)、t114でTOSのロードをハイジャックしてセキュアコンテキストでのコード実行を取得する場合、あるいは単にシェルコードをロードして機密情報をダンプする場合も同様です。
悪用は、セカンダリイメージをペイロード/シェルコードとして使用し、addr/lenフィールドをペイロードのサイズと配置先に適切に設定したブートイメージを作成するだけです。イメージはわずか4バイトにすることもできます。
t124+デバイスでは、nvtbootが起動の初期段階でTOSをロードし、その後、後期段階のブートローダー(EBT)に実行を引き渡すため、セキュアコンテキストはありません。しかし、この後期段階のブートローダーにはメモリ内で自由に書き込むことができます。脆弱なブートローダーはカーネルをロードするものなので、任意の未署名コードを実行したい場合には依然としてかなり価値があります。
ロードアドレスが検証されないだけでなく、サイズも検証されません。そのため、悪意のあるsecondary_sizeフィールドを作成してさまざまな変数/ポインタをオーバーフローできることから、CVE-2019-5699への扉が開かれます。ただし、これは最初のセキュリティ速報が公開された後に後から気づいただけなので、私の手柄にすることはできません。また、かなり多くの作業が必要なようです...
t114:
IROM->BCT->EBT->TOS->KERNEL
t124+(新しい64ビットSoCでは若干異なる場合があります):
IROM->BCT->NVTBOOT->TOS->EBT->KERNEL
この問題は当初、2019年7月29日にNvidiaのPSIRT(製品セキュリティインシデント対応チーム)に報告されました。同チームからは、関連するすべての顧客に通知され、修正が展開されるまで開示を延期するよう丁寧に要請され、私は快く応じました。彼らはプロセス全体を通じて連絡を取り合い、協力的でした。本日(2019年12月5日)、Nvidiaはようやく影響を受けるコードへの修正のリリースを完了し、この問題を反映した2つの異なるセキュリティ速報を公開するとともに、開示のゴーサインをくれました。
https://nvidia.custhelp.com/app/answers/detail/a_id/4875
https://nvidia.custhelp.com/app/answers/detail/a_id/4910
balika011
beaups
npjohnson
djrbliss/Dan Rosenberg には、ブートローダーがブートイメージヘッダーを解析する方法を細かく確認させてくれたことに感謝します。