Microsoft Azure Sphere 向けのバグ発見コンテストで、Cisco Talos が 16 件の脆弱性を報告
Microsoft 社は 2020 年 5 月 15 日に、Azure Sphere のバグ発見を目的とした 3 か月間の「Azure Sphere バグ発見コンテスト(ASSRC)」を開始しました。選抜されたチームと個人が 3 か月にわたって繰り広げた今回のコンテストにおいて、Cisco Talos はさまざまな重大度の脆弱性を合計 16 件報告しました。その中には、Azure Sphere の Capability 権限(Azure Sphere のコンテキストにおいて最も重要な Linux の Normal World 権限)を取得可能な権限昇格バグチェーンも含まれています。
Azure Sphere プラットフォームは、IoT アプリケーション セキュリティ専用に設計された、クラウド接続型のカスタム SoC です。`内部はさまざまな役割(さまざまなタイプのアプリケーションの実行、セキュリティの適用、暗号化の管理など)を担う複数の ARM コアセットで構成されています。対外的には、Microsoft 社の Azure Cloud によってサポートされています。セキュリティ更新やアプリケーションの展開を処理し、定期的にデバイスの整合性を検証して Azure Cloud へのアクセスを許可するかどうかを決定すること、それが Azure Sphere の役割です。Azure Sphere の更新と展開には Azure Cloud が使われますが、それとは別に利用者独自のサーバを利用できるのが特徴です。
利用者は、Azure Sphere クラウドテナント(開発モードの場合はサイドロード)としてグループ化されているデバイスに署名済みアプリケーションをプッシュしますが、デフォルトではごく限られた権限しか付与されません。IP アドレスやホスト名への接続、ディスクへのデータ保存、ソフトウェアの更新の延期といった基本機能を使用するには、各アプリケーションの app_manifest.json 内で事前に定義しておく必要があります。これらを定義することで、特定の機能を使用するために必要となる特定の Linux グループ ID(GID)や Linux 機能が、アプリケーション(インストールごとに異なる)のユーザ ID(UID)に付与されるようになります。
広い視点から見ると、すべてのシステムアプリケーション(networkd、azcore、azured など)には、必要な機能以外にはアクセスできないように、特定の Linux 機能や Azure Sphere 機能の権限のみが付与されます。これらの Azure Sphere 機能は、通常の Linux 機能と異なる形で保持・処理されます。これにより Azure Sphere 固有の重要なインターフェイスへのアクセスが制限されます。多くの場合、Azure Sphere 機能は、特に /dev/pluton および /dev/security-monitor の ioctl へのアクセスを制限する目的で使用されます。最も重要な機能が存在するのはこれら 2 か所となるため、必然的に実行権限も最高レベルが必要になります。
以下に、システムの論理チャートを示します。
Azure Sphere プラットフォームは、利用者が(約 600 KB 以下の)任意のアプリケーションをフラッシュできるセキュアな IoT 環境として設計されています。そのためコンテストで最も注目したのは、「利用者のアプリケーションが侵害されてコードが実行された場合、そこから何を実行できるのか?」という点です。この点はコンテストの公式課題にも反映されています。それらの課題を以下にご紹介します。
- Pluton でコードを実行できるか?
- Secure World(security-monitor)でコードを実行できるか?
- ローカル攻撃(侵害された顧客のアプリケーション)またはリモート(外部ネットワーク)を介して NetworkD 上でコードを実行できるか?
- Linux 下での純粋な Return Oriented Program(ROP)以外に、署名のないコードの実行を許可できるか?
- アプリケーション マニフェストに記載されている権限以外に特権を昇格できるか?(例:ユーザ ID の変更、バイナリへのアクセスの追加)
- サインインしてなく、保存された機能がないテナントに対して要求された場合に、製造状態が DeviceComplete のデバイスでソフトウェアおよび構成オプションを変更できるか?(完全なデバイスリセットを除く)
- アプリのマニフェストにない他のドメインへの通信を行えるようにファイアウォールを変更できるか?(注:DNS ポイズニングを除く)
本稿では、公式課題である上記のカテゴリに基づいて 16 件の脆弱性を分類しています。また、公式課題には含まれないサービス拒否の脆弱性に関するセクションも設けています(各脆弱性の重大度や、他の脆弱性のエクスプロイトに必須かどうかについては触れていません)。
未署名コードの実行
なぜ「未署名コード実行の脆弱性」が着目されているのでしょうか?なぜなら Azure Sphere のセキュリティモデルでは、Azure Sphere デバイスで実行されるすべてのコードが Microsoft またはアプリケーション開発者によって署名されている必要があるからです。具体的に言うと、デバイス上の実行可能データはすべて、Azure Sphere アプリケーション(および RootFS)を構成する ASXipFS パーティション内に存在している必要があります。ASXipFS ファイルシステム カーネル ドライバは書き込みを一切サポートしておらず、(不揮発性データの保存に使用される)Littlefs ファイルシステムも noexec としてマウントされます。Azure Sphere は W^X のコンセプトをプロセスメモリからディスク自体に拡張することにより、ファイルシステムを介して W ^ X 保護を事実上、デバイス全体に適用します。ASXipFS は Android の DM-Verity にほぼ相当する仕組みです。ブロックを常に確認したり、フラッシュメモリを摩耗(寿命低下)させたりすることなく、ディスクの整合性を維持します。
カスタムの Azure Sphere Linux セキュリティモジュール(LSM)には、攻撃者がページのアクセス許可を変更したり、プロセスメモリにコードを挿入したりするのを防ぐために、mprotect / mmap の syscall に対する保護機構が実装されています。過去に書き込み可能だったページに対しては、仮想メモリページの VM_MAY* フラグを使用することで、権限を実行可能に変更することを禁止します(そもそも、書き込み可能かつ実行可能なページをマッピングすること自体を禁止します)。この保護機構はほとんどのケースで効果を発揮しますが、Talos は未署名コードを実行できる 5 種類の方法を発見しました。コンテストの第 3 週までに、バージョン 20.05 の脆弱性として次の 2 件を報告しました。
Microsoft Azure Sphere の Normal World コード実行機能(ptrace API)に起因する、未署名コード実行の脆弱性(TALOS-2020-1090)
Microsoft Azure Sphere の Normal World コード実行機能(/proc/self/mem)に起因する、未署名コード実行の脆弱性(TALOS-2020-1093)
TALOS-2020-1090 の脆弱性では、ptrace を使用して現在のプロセスの fork() にアタッチし、ptrace の POKETEXT コマンドを使用して .text セクションが存在する実行可能(書き込み不可)メモリ領域を改ざんできます。一方、TALOS-2020-1093 では、/proc/self/mem への書き込みを行うことにより、プロセスのメモリを開いて改ざん可能です。
これらは極めて簡単に発見できる脆弱性ですが、ASSRC には多数の研究者が参加していたため、できるだけ早く報告することが重要と判断しました。以前の課題で Trail of Bits 社が /proc/self/mem の脆弱性を報告していたにもかかわらず、修正が ASSRC の開始に間に合っていなかったことが後で判明したことも、早急な報告の必要性を裏付けています。これらの問題は 20.07 で修正されました。
その後、Talos は 20.06 で未署名コード実行に関連する次の 2 件の脆弱性を発見しました。
Microsoft Azure Sphere の Normal World コード実行機能(READ_IMPLIES_EXEC パーソナリティ)に起因する、未署名コード実行の脆弱性(TALOS-2020-1128)
Microsoft Azure Sphere の Normal World コード実行機能(PACKET_MMAP)に起因する、未署名コード実行の脆弱性(TALOS-2020-1134)
TALOS-2020-1128 は、Linux の READ_IMPLIES_EXEC パーソナリティを使用して、read 権限を要求するすべての mmap コールに exec 権限も付与します。これにより、特定の syscall で読み取りおよび書き込み権限を要求するだけで rwx マップを作成できるようになります。この問題は 20.08 で修正されています。
TALOS-2020-1134 は、(コード実行機能 CAP_NET_RAW を必要とし、networkd のみが保持する)AF_PACKET ソケットタイプを使用して read+exec メモリマップを作成し、カーネルによって書き込まれるリングバッファを保持します。リングバッファには受信したネットワークパケットが書き込まれるため、攻撃者はメモリマップの内容を制御することで、事実上、マップに対する書き込み権限と読み取り権限の両方を取得できます。この問題は 20.09 で修正されています。
上記 2 件の未署名コード実行方法は、前述の 2 件よりも明らかに興味深いものです。単にヒューリスティックテストを行うだけでなく、カーネルのソースコードを実際に読む必要があるからです。しかし、20.07 のリリース直後に、/proc/self/mem の脆弱性の修正が不完全だったことに起因する、別の未署名コード実行方法が見つかりました。
Microsoft Azure Sphere の Normal World コード実行機能(/proc/thread-self/mem)に起因する、未署名コード実行の脆弱性(TALOS-2020-1138)
TALOS-2020-1093 で発見された /proc/self/mem のバグは 20.07 で修正されましたが、ターゲットを /proc/thread-self/mem に変えることで、同じ根本原因による問題を引き起こすことが可能でした。この問題は 20.08 で修正されています。
サービス拒否
特定の権限昇格チェーンを完了するには再起動が必要であり、かつ今回挙げたサービス拒否の脆弱性のうち 2 件は修復にデバイスのリカバリが必要だと考えられます。しかしいずれの点についても、本稿では割愛します。まず、最も単純なサービス拒否の脆弱性について説明します。AzureSphere 20.05 では、どのユーザも非同期の ioctl 要求を /dev/pluton に繰り返し送信するだけでデバイスを攻撃することができました。
Microsoft Azure Sphere の非同期 ioctl 関数に起因する、サービス拒否の脆弱性(TALOS-2020-1117)
非同期 ioctl を繰り返し発行することで、Linux カーネルが Pluton M4 コアとの通信に使用するリングバッファを満杯にすることが可能でした。Pluton は、非同期メッセージを配置するためにリングバッファ内の空のスポットを継続的に探し続けますが、空のスポットが見つからないとすぐにウォッチドッグがトリガーされて、デバイスが再起動されます。この脆弱性は、おそらく別のバグチェーンを完了するために再起動が必要な状況に限って影響を及ぼすものだったと考えられますが、20.07 で修正され、/dev/security-monitor と /dev/pluton に対する非同期 ioctl は完全に削除されました。
Microsoft Azure Sphere の Littlefs クォータに起因する、サービス拒否の脆弱性(TALOS-2020-1129)
TALOS-2020-1129 では、littlefs パーティション(/mnt/config)に対して書き込み権限を持つ任意のユーザが、truncate() syscall によるファイルシステム クォータ バイパスを利用することにより、/mnt/config 内のほぼすべてのファイルシステム操作が littlefs コードベース内で無限ループする状態を引き起こすことができます。この状態が発生すると、ハードウェアウォッチドッグにより再起動されます。設計上 /mnt/config は永続的であるため、この脆弱性がエクスプロイトされると、手動でリカバリしないかぎりデバイスは使用不能になります。この問題は 20.09 で修正されています。
Microsoft Azure Sphere Pluton の SIGN_WITH_TENANT_ATTESTATION_KEY に起因する、メモリ破損の脆弱性(TALOS-2020-1139)
Azure Sphere 20.07 の Pluton でもサービス拒否の脆弱性が見つかりました。20.06 から 20.07 への更新に伴い、ioctl オブジェクト定義は、オープンソースの Azure Sphere カーネル内ではなく、Security Monitor と Pluton を構成するそれぞれのバイナリ BLOB 内に移動されました。また、/dev/pluton デバイスと /dev/security-monitor デバイスで極めて大量のコードが変更されました。このコード変更により、Pluton ioctl の数は 13 個から 2 個に減少しました。1 つは(以前の ioctl をすべて包摂する) PLUTON_SYSCALL ioctl で、もう 1 つは SIGN_WITH_TENANT_ATTESTATION_KEY ioctl です(こちらは最終的に Pluton の syscalls と同じコードパスに入ることになります)。Talos が報告した脆弱性は、後者の ioctl に存在しています。
すべての Pluton システムコールには固有のサイズチェックがありますが、SIGN_WITH_TENANT_ATTESTATION_KEY に渡される struct azure_sphere_digest 引数には、チェックされないサイズフィールドを持つ構造がネストされていました。その結果、Pluton のメモリスペースで境界外書き込みが発生し、デバイスパニックが引き起こされてサービス拒否が生じます。この問題は 20.09 で修正されています。
情報漏えい
情報漏えいの脆弱性について言えば、難易度の低い次の 1 件をコンテスト開始から 2、3 数週間以内に特定しました。
Microsoft Azure Sphere のカーネルメッセージのリングバッファに起因する、情報漏えいの脆弱性(TALOS-2020-1089)
この問題に関する報告では、カーネルリングバッファへのアクセスによって、カーネルやプロセスのアドレスをはじめとするメモリ内の機密情報を漏えいさせる方法について詳しく説明しています。アドバイザリでは、application-manager(init プロセス)から ASLR オフセットを漏えいさせる方法を紹介しています。この問題は 20.07 で修正されています。
また、さらに複雑なシーケンスを使用すれば、littlefs ファイルシステムを介してカーネルメモリをダンプすることも可能でした。
Microsoft Azure Sphere の Littlefs truncate 関数に起因する、情報漏えいの脆弱性(TALOS-2020-1130)
新しいファイルに数バイトを書き込んでバッキングメモリをキャッシュし、sys_truncate() を呼び出して拡張した上で、同じファイルから読み取りを行うと、すでに解放されているものの、再利用時にクリアされていないカーネルの仮想メモリページを読み取ることができました。この問題は 20.09 で修正されています。
権限昇格チェーン
最初にお断りしておきますが、次の 2 件の脆弱性については、McAfee ATR がほぼ同じチェーンについての報告を Talos よりも先に行っているため、ここでは詳しく取り上げません(ただし、個別の記事では詳しく説明しています)。
Microsoft Azure Sphere の ASXipFS inode TYPE 関数に起因する、権限昇格の脆弱性(TALOS-2020-1131)
Microsoft Azure Sphere の mtd 文字デバイスドライバに起因する、権限昇格の脆弱性(TALOS-2020-1132)
これらは 20.07 で修正されました。McAfee ATR の報告と矛盾する点もありますが、厳密に言うと両者の間には /mnt/config/uid_map ファイルを改ざんする方法に違いがあり、Talos は最終的に AZURE_SPHERE_CAP_ * 機能を使用する方法を取りました。Talos は、UID ラッピングを発生させるのではなく、アプリケーションの UID を azured システムアプリケーションと同じにする方法で uid_map を改ざんすることに成功しました。
Microsoft Azure Sphere の uid_map 機能(UID の一意性)に起因する、権限昇格の脆弱性(TALOS-2020-1137)
uid_map を改ざんした後、サービス拒否の脆弱性の 1 つをエクスプロイトしてデバイスを再起動させると、アプリケーションが別のアプリケーションの UID で実行されるようになりました。この問題は 20.08 で修正されています。
Microsoft Azure Sphere のアクセス制御機能(Capability)に起因する、権限昇格の脆弱性(TALOS-2020-1133)
Talos では、各プロセスがより高い権限を必要とする AZURE_SPHERE_CAP_ * 機能を使用可能な(ただし UID は同じ)別のプロセスを ptrace できるかどうかについて、権限チェックが行われていないことも発見しました。したがって、ルートを完全にスキップし、azured プロセス(または別のシステムアプリケーション)を ptrace してシェルを挿入することで、より高い権限を必要とする /dev/security-monitor および /dev/pluton ioctl に直接移動することが可能でした。
この脆弱性は 20.09 で修正されています。
権限昇格(チェーン以外)
最初の 1 か月以内に、メモリ破損に関連する上記とは別の脆弱性も見つかりました。ただし、実際にエクスプロイト可能かどうかの検証は行っていません。
Microsoft Azure Sphere の AF_AZSPIO ソケットに起因する、メモリ破損の脆弱性(TALOS-2020-1118)
Azure Sphere 固有の AF_AZSPIO ソケットを 2 回バインドするだけで、カーネルリストの二重解放を引き起こすことが可能でした。その結果 null の間接参照が発生し、(null ページをマッピングできる場合)カーネル内でメモリ破損が引き起こされる可能性があります。この問題は 20.07 で修正されています。
研究者による振り返り
Azure Sphere は、仕様とセキュリティの両面でさまざまな制約が課されているため、非常に研究のしがいがあるデバイスでした。調査ではまず、カーネルを詳細にテストするために使用されることが多い不完全な QEMU インスタンスをセットアップする前に、busybox の .imagepackage を書き込んでデバイス内部をしっかりと把握することに努めました。デバイスの他のコアやチップに影響する問題に関しては、主に C 言語のプログラムと gdbserver を書き込んで調査を行いました。Azure Sphere は非常に複雑で、チップセットと環境の仕様が一部しか公開されていないため、既製のツールを利用してもあまり効果が上がらず、作業効率も悪くなるだろうと判断したからです。2 つのバイナリを格納できるスペースがなく、ユーザアプリケーション用のスペースが約 600 KB に制限されていたため、busybox 内で strace を実行するといった単純な作業でさえ、かなり骨が折れました。しかし、使用するツールをシンプルなものだけにとどめたことが功を奏し、ASSRC コンテストの期間内に多数の脆弱性をすばやく発見することできました。Talos が利用したツールは基本的に tmux、Vim、Binary Ninja、QEMU(最終段階で使用)、GDB だけです(一部では SublimeText も使われましたが、これは余計だったと思います)。
月単位よりも短い周期でセキュリティ更新がリリースされる上、約 70 人が同時に調査に当たるという今回の ASSRC では、少ないツールで手早く調査を行える研究者が有利だったと考えられます。攻略が極めて難しいターゲット(pluton と security-monitor)を取り扱うには、エミュレーション環境をセットアップするか、権限昇格チェーンを発見することが必須条件でしたが、3 か月のコンテスト期間中に達成するにはどちらも時間がかかりすぎるため、断念せざるを得ませんでした(もちろん、「XYZ 権限を取得できたと仮定した場合……」という但し書き付きのバグ報告を Microsoft 社が認めてくれることを期待するという、奥の手も利用できなくはありませんが)。また、20.07 がリリースされた時点で、それまでに見つかっていた権限昇格チェーンがすべて修正されたため、pluton と security-monitor を動的にテストする方法が一切なくなりました。
付け加えておきますが、毎月のセキュリティ更新は、最新のセキュリティパッチを配布してデバイスを最新状態に保つ Azure Sphere セキュリティモデルの一環であり、コンテスト参加者にはどうすることもできません。毎月のセキュリティ更新は既知のバグを迅速に修正する上で極めて効果的です。しかしコンテスト期間中のセキュリティ更新により、研究者は攻撃者よりもはるかに不利な立場に置かれ、結果的にデバイスの調査がかなり不完全なものに終わってしまった感は否めません。発見が容易な脆弱性が報告されて直後に修正されるというサイクルを繰り返すため、研究者はより難しい問題に取り組まざるを得なくなるからです。この種の旗取りゲームでは、手軽に攻略できるターゲットだけに皆が群がり、攻略が困難で重大度の高い攻撃対象領域が未調査のまま放置されてしまうのではないかと懸念されます。
最後に、イベントの主催者と、コンテスト中に多大な協力や助言を与えてくれた Azure Sphere の技術スタッフに感謝の意を表します。全体的な観点からは(バグ報告に対する応答の内容やスピードの一貫性などに)いくつか問題がありましたが、総じて今回の ASSRC は非常に有意義で、Azure Sphere のセキュリティ態勢の向上に資するものだったと思います。
まとめ
Azure Sphere 向けのバグ発見コンテストに 3 ヵ月間取り組んだ結果、Azure Sphere プラットフォームに 16 件の脆弱性を発見し、報告しました(TALOS-2020-1141 はまだ修正されていないため未公開のままです)。各脆弱性の詳細については、個々の脆弱性に関する上記の記事を参照してください。
カバレッジ
脆弱性のエクスプロイトは、以下の SNORTⓇ ルールで検出できます。今後、脆弱性に関する新たな情報が追加されるまでの間は、ルールが追加されたり、現行のルールが変更されたりする場合がありますのでご注意ください。最新のルールの詳細については、Firepower Management Center または Snort.org を参照してください。
Snort ルール:54501 ~ 54504、54645 ~ 54648、54680 ~ 54683、54701 ~ 54702、54829 ~ 54732、54829 ~ 54830
本稿は 2020 年 10 月 6 日に Talos Group のブログに投稿された「90 days, 16 bugs, and an Azure Sphere Challenge」の抄訳です。