Back That App Up: Lenovo Vibe の root 化

2016 年 5 月、Mandiant のレッド チームは、Lenovo の Vibe P1 Android ベースのモバイル デバイスに存在する一連の脆弱性を発見しました。この脆弱性により、ユーザー「ルート」へのローカル権限昇格が可能になります。 Mandiant は 2016 年 5 月にこれらの脆弱性を Lenovo に開示しました。Lenovo は、Motorola と協力すべきであると Mandiant にアドバイスしました。その後、Mandiant は Motorola に修正のために脆弱性を開示しました。 Mandiant の Red Team が発見した脆弱性は次のとおりです。

  • Lenovo の「セキュリティ」アプリケーションで有効化されたローカル バックアップ (CVE-2017-3750)
  • Lenovo の「Idea Friend」アプリケーションでローカル バックアップを有効化 (CVE-2017-3749)
  • 「nac_server」バイナリの不適切なアクセス制御 (CVE-2017-3748)

影響を受けるデバイスとソフトウェアのバージョンを含むLenovo の公式アドバイザリは、Motorola の Web サイトで確認できます。 Motorola は、これらの脆弱性にパッチが適用されたことを示しており、同社はこの投稿のリリースに関して Mandiant をサポートしています。

FAQ で一般的な詳細を提供しており、脆弱性の技術的分析が続きます。

よくある質問

どのデバイスが影響を受けており、(潜在的に) 何台のデバイスが影響を受けていますか?

この投稿で説明されている脆弱性は、Lenovo ブランドのデバイスのサブセットに影響を与えます。影響を受けるデバイスの完全なリストは、 Motorola の公式アドバイザリに記載されています。この投稿で説明されている脆弱性は、Google が開発した Android オープン ソース プロジェクト (「AOSP」) には影響しないことに注意してください。

問題はどのように対処されていますか?

Motorola は、より安全なプロセスを使用するために、影響を受けるメカニズムを再設計しました。

攻撃者はこれらの脆弱性をどのように悪用しますか?

説明されているエクスプロイト チェーンには、デバイスへのローカルの物理アクセスが必要です。したがって、このエクスプロイトが「実際に」見られる可能性はほとんどありません。デバイスを Lenovo が提供する最新のソフトウェア パッケージに更新し、強力なロック画面設定を使用してデバイスを保護することをお勧めします。

これらの脆弱性を発見したのは誰ですか?

ジェイク・バレッタ ( @jake_valletta )

テクニカル分析

ここで、公開された脆弱性を独自の方法で連鎖させることにより、Mandiant のレッド チームがユーザー「ルート」としてコードを実行するために使用したエクスプロイト プロセスについて説明します。

ターゲットの特定: 「nac_server」

Android デバイスで特権をエスカレートする一般的なプロセスは、ローカルでリッスンしているソケットを列挙することです。 AF_INET ソケット (IP アドレスと TCP/UDP ポートを考えてください) が Android デバイスでローカルにリッスンすることはまれですが、AF_UNIX ソケット (以降、「UNIX ソケット」と呼びます) は「netd」、「installd」などのネイティブ Android デーモンによって頻繁に使用されます。および「vold」は、そのほとんどが昇格された権限で実行されます。 UNIX ソケットは、ファイル システム上のファイルとして表され、通常は「/dev/socket/」ディレクトリ内のソケット タイプのファイルにバインドされます。 UNIX ソケットの特定のサブセットは、抽象名前空間 (ファイルシステムに基づくファイルにバインドされていない) にバインドされ、「@android:debuggerd32」や「@jdwp-control」などの先頭に「@」文字で示されます。 .

テスト Vibe で「busybox」ユーティリティの「netstat」モジュールを使用すると、図 1 で強調表示されているように、Android オープン ソース プロジェクト (「AOSP」) の一部ではない興味深い抽象ソケットに注目できます。この記事では、Android Debug Bridge (「adb」) を使用して、テスト用の Lenovo Vibe とやり取りします。

Figure 1
図 1: テスト用 Lenovo Vibe デバイスの抽象的なソケット

これらの UNIX ソケットの原因となっている可能性のあるバイナリを見つけるには、デバイス上のすべての DEX バイトコードとバイナリの文字列検索が役立ちます。システム バイナリ (デバイスのディレクトリ “/system/bin/”、”/vendor/bin/”、および “/system/xbin/” にあります) に対する文字列検索では、文字列 “nac_server”、”nac_safe_server” が示されました。 、および「supercmdlocalsocket」はすべて、非 AOSP バイナリであるバイナリ ファイル「/system/bin/nac_server」に存在していました。

これを確認するには、Vibe にある「/init.rc」ファイルを抽出して表示します。このファイルでは、図 2 に示すように、Lenovo が「nac_server」というinit サービスを追加したことがわかります。

図 2
図 2: 「/init.rc」ファイルで定義された「nac_server」サービス

「init」プロセスは「nac_server」サービスを登録し、システムの起動時にユーザー「root」として実行します。これは、「init.svc.nac_server」システム プロパティを確認し、テスト デバイスで実行中のプロセスを確認することで確認できます (図 3 と図 4 を参照)。また、「nac_server」バイナリがSE for Android (「SEAndroid」)コンテキスト「nac_server」で実行されていたことに注意することも重要です。

図 3
図 3: 「init.svc.nac_server」システム プロパティの確認
図 4
図 4: 「root」ユーザーおよび「nac_server」SEAndroid コンテキストとして実行される「nac_server」プロセス

このプロセスは特権プロセスとして実行され、UNIX ソケットをリッスンすることがわかっているため、分析を「nac_server」バイナリに移して、その完全な機能を理解しました。

「nac_server」のバイナリ解析

「nac_server」バイナリの機能を詳しく説明するために、Mandiant のレッド チームは、FireEye Labs Advanced Reverse Engineers (「FLARE」) (@m_r_tz に叫ぶ)と協力しました。上記のように、「init」プロセスは、ユーザー「root」としてのシステム起動時に「/system/bin/nac_server」を開始します。 「nac_server」が開始されると、「nac_server」、「nac_safe_server」、「supercmdlocalsocket」の 3 つのスレッドが生成され、それぞれが抽象的な UNIX ソケットにバインドされます。これらの各スレッドは、ソケットを介してクライアントからファイル パスを受信することを想定しています。 「nac_server」は、ファイル パスに基づいて次のセキュリティ チェックを実行します。

  • 「/」に基づいてファイル パスをトークン化し、3 番目の要素が呼び出し元のパッケージ名であり、4 番目の引数が実行するファイルであると想定します。次に、図 5 に示すように、パッケージ名がホワイトリストと照合されます。
図 5
図 5: 「nac_server」内のホワイトリストに登録された Lenovo ブランドのアプリケーション
  • 「/data/system/packages.xml」ファイルを解析して、呼び出し元のパッケージ名がインストールされているかどうか、署名が内部署名のリストと一致するかどうかを確認します。許可されている署名の 1 つを図 6 に示します。
図 6
図 6: 「nac_server」にハードコードされたパッケージ署名

「nac_server」は、ファイル パスを検証した後、第 4 引数のファイルを「/data/local/root_channel/[package_name]」ディレクトリにコピーし、SEAndroid コンテキストを「root_channel」に設定してから、「system」を使用してファイルを実行します。 (..)」はユーザー「root」として機能します。次のセクションでは、「root_channel」SEAndroid コンテキストの重要性と機能について説明します。

つまり、「nac_server」バイナリは、Lenovo によって署名されたアプリケーションが特権プロセスおよびコンテキストとしてファイルを実行するためのメカニズムを提供します。この機能を含めるには、明らかに悪意のある理由があります。ただし、Mandiant の調査では、Lenovo がこの機能を使用して、Android ランタイムからカスタムの「iptables」ファイアウォール ルールを作成したことが示唆されています。

「nac_server」は呼び出し元がファイル パスの 3 番目のトークンであると誤って想定しているため、サービスを混乱させて、制御するファイルをサービスにフィードすることができます (CVE-2017-3748)。

SEAndroid コンテキストについて

SEAndroid は、Android 4.3 (「Jelly Bean」) 以降の Android デバイスに追加されたセキュリティ機能です。 SEAndroid を採用する主な理由の 1 つは、「システム」、「ラジオ」、「ルート」に関連付けられた強力な UID の詳細なセキュリティ制御を提供することでした。このセクションは、SEAndroid の完全なチュートリアルではないことに注意してください (SEAndroid のより包括的な説明については、こちらを参照してください)。分析対象の SEAndroid 関連ファイルは次のとおりです。

  • /sepolicy – システムの起動時に読み込まれるバイナリ カーネル ポリシー ファイル
  • /seapp_contexts – SEAndroid ドメインと Android アプリケーションのタイプを決定するためのルール
  • /etc/security/mac_permissions.xml – Zygote プロセスが新しいアプリケーションを生成するときに適用する正しいドメインを決定するための x.509 証明書情報 (Zygote プロセスの詳細については、こちらを参照してください)

「nac_server」UNIX ソケット分析

残念なことに、組み込みの「シェル」ユーザーとして前述の 3 つの UNIX ソケットのいずれかに接続しようとすると、SEAndroid ポリシー違反が発生します。図 7 は、 「socat」ユーティリティを使用して UNIX ソケット「supercmdlocalsocket」に接続しようとしたときの「Permission denied」エラーを示しています。

図 7
図 7: 「socat」を使用して「supercmdlocalsocket」抽象ソケットへの接続を試みる

図 8 は、Android ログ バッファーにキャプチャされた SEAndroid ポリシー違反を示しています。

図 8
図 8: Android ログ バッファに含まれるポリシー違反

図 8 では、オペレーティング システムがソース コンテキスト「シェル」、つまり「nac_server」タイプの「unix_stream_socket」クラスの「connectto」権限を拒否したことがわかります。研究者として知りたいのは、誰がこのアクセス許可にアクセスできるかということです。これに答えるには、次のように「sesearch」ユーティリティを使用できます。

図 9
図 9: 「sesearch」を使用して「connectto」権限のルックアップを実行する

このツールを実行すると、「system_app」、「platform_app」、「unconfineddomain」の 3 つの SEAndroid ドメインが正しい権限を持っていることがわかります。幸いなことに、「platform_app」または「system_app」セキュリティ ドメインで 100 を超えるアプリケーションが実行されています。これに基づいて、次の目標は、「system_app」ドメインまたは「platform_app」ドメインでコードを実行して、「nac_server」UNIX ソケットに接続できるようにすることです。

「root_channel」分析

コマンドを実行する直前に「nac_server」バイナリが適用する「root_channel」SEAndroid コンテキストの機能を調べることも価値があります。 Lenovo Vibe では、「root_channel」コンテキストは非常に強力で、アプリケーション データと Android ランタイムへのフル アクセスと、「/data/」ファイル システムへの書き込みアクセスが含まれます。このコンテキストに欠けているのは、ファイルシステムをマウントまたは再マウントし、SEAndroid を無効にする機能です (これは読者の課題として残しておきます)。

ローカル バックアップによる「nac_server」バグのトリガー

Android は、Android 2.2 (「Froyo」) でローカル バックアップを導入しました。ローカル バックアップを使用すると、USB デバッグが有効になっているデバイスに物理的にアクセスできるユーザーは、特定のアプリケーションのアプリケーション データをダウンロードし、このデータをデバイスに復元できます。アプリケーションをバックアップできるかどうかの決定は、アプリケーションの「AndroidManifest.xml」ファイル内の「android:backupAllowed」属性によって制御されます。デフォルトでは、この値は、共有 UID「android.uid.system」として実行されているアプリケーションを除くすべてのアプリケーションで「true」に設定されています。

アプリケーションのバックアップをローカルに作成するには、図 10 に示す「adb」コマンド「backup」を使用できます。

図 10
図 10: 「adb」を使用して「com.some.app」アプリケーションのローカル バックアップを作成する

これらのローカル バックアップは、オープンソースのAndroid Backup Extractor (「abe」)と「tar」ユーティリティを使用して解凍できます。これらのバックアップは署名されていないため、構成ファイルを編集したり、新しいファイルを完全に追加したりするなど、バックアップを自由に変更できます。バックアップを再パッケージ化するには、手順を逆にして、「tar」(または「 pax 」ユーティリティ)、「abe」、最後に「adb」コマンド「restore」を使用して、デバイスにバックアップを復元します。図 11 は、バックアップを復元するコマンドを示しています。

図 11
図 11: 「adb」を使用した新しいローカル バックアップの復元

バックアップの悪用パート 1: コードの実行 (CVE-2017-3749)

ローカル バックアップを許可することの特に危険な副作用の 1 つは、悪意のあるユーザーが、アプリケーションが知らないうちにアプリケーションのプライベート ファイルを変更できることです。これには通常、アプリケーションの動作を変更するための構成ファイルの変更 (Angry Bird のハイスコア データの変更など) が含まれますが、まれに、攻撃者がアプリケーションの一部として含まれる補助的な DEX バイトコードを変更して、アプリケーションを完全に制御することができます。 .アプリケーションのプライマリ DEX バイトコードはインストール時に処理され、アプリケーションのデータ ディレクトリの外に保存されるため、ターゲットではないことに注意してください。

これは、Lenovo ブランドの連絡先管理アプリケーションである Idea Friend アプリケーション (「com.lenovo.ideafriend」) の場合です。このアプリケーションは特権 UID として実行されませんでしたが、「platform_app」SEAndroid ドメインで実行されました (図 12 参照)。

図 12
図 12: 「platform_app」セキュリティ コンテキストで実行されている「com.lenovo.ideafriend」アプリケーション

補足バイトコードの識別と変更

前述のプロセスを使用して Idea Friend アプリケーションのローカル バックアップを作成すると、ディレクトリ「f/parse/」が表示されます (これは、「/data/data/com.lenovo.ideafriend/files/parse/」に対応します)。テスト デバイス) には、図 13 に示すように、14 個の署名付き Java JAR アーカイブが含まれており、それぞれに DEX バイトコードが含まれています。

図 13
図 13: Idea Friend バックアップの「f/parse/」ディレクトリに含まれる JAR アーカイブ

JAR ファイル「ParseUtilBubble_8.jar」および「parseUtilMain_8.jar」に含まれる DEX コードは、起動時に Idea Friend アプリケーションによって動的にロードされます。つまり、これらの JAR ファイルを変更できれば、Idea Friend として任意のコードを実行できます。応用。これらの JAR ファイルは署名されているため、アーカイブの内容を変更することはできません。ただし、テスト デバイスはAndroid ランタイム (「ART」)を利用しているため、オペレーティング システムは「dex2oat」を使用して DEX バイトコードを自動的に最適化し、署名されていない ELF バイナリを生成します。この動作を確認するために、ディレクトリ「r/app_outdex」(テスト デバイスの「/data/data/com.lenovo.ideafriend/app_outdex/」に対応) に 2 つの OAT ファイルがあります。図 14 は、ディレクトリ「r/app_outdex/」にある JAR ファイル「ParseUtilBubble_8.jar」および「parseUtilMain_8.jar」から最適化された OAT バイナリを示しています。図 15 は、これらが ELF バイナリ (ART で使用されるファイル形式) であることを確認しています。 .

図 14
図 14: Idea Friend バックアップ内の最適化された OAT バイナリ
図 15
図 15: ART バイナリのファイル タイプの判別

Black Hat Asia 2014 のホワイト ペーパー「Hiding Behind ART」で説明されている手法を使用すると、元の DEX バイトコードを指定して独自の OAT ELF バイナリを作成できます。プロセスは次のように要約されます。

  1. 既存の DEX バイトコードを逆アセンブルします。これには、 「baksmali」を使用できます。
  2. 逆アセンブルされた DEX バイトコードを変更します。この場合、LocalSocket クライアントを追加して、Idea Friend アプリケーションによって呼び出されることがわかっているメソッド内の UNIX ソケット「supercmdlocalsocket」に接続します (詳細については、このまま読み進めてください)。
  3. 新しい DEX を再構築します。これには「smali」を使用できます。
  4. 新しい DEX バイトコードを、宛先ファイル名と正確に一致するファイル名でデバイスにプッシュします。たとえば、宛先ファイル名が「/data/data/com.lenovo.ideafriend/app_outdex/parseUtilMain_8.dex」の場合、ファイル名の正確なサイズが 63、つまり「/data/local/tmp/」のファイルをプッシュする必要があります。 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.jar」。これは後のステップで重要です。
  5. テスト デバイスで DEX バイトコードに対して「dex2oat」ユーティリティを手動で呼び出して、最適化された OAT ファイルを生成します。
  6. テスト デバイスから新しい OAT バイナリをプルします。
  7. OAT DEX ファイル ヘッダーのパディングされたファイル名 (「dex_file_location_data」フィールドに対応) を元のファイル パスに置き換えます。適切な長さにパディングしたため、バイナリのオフセットには影響しないことに注意してください。 vim や 010 などのテキスト エディタがここで機能します。
  8. DEX ヘッダーの「dex_file_location_checksum」CRC32 チェックサムを元の OAT バイナリのチェックサムにリセットします。このために、「dexdump」を使用してチェックサムを取得し、「dd」を使用してそれを置き換えることができます。

このプロセスを Idea Friend アプリケーションのローカル バックアップと組み合わせて使用し、「nac_server」バイナリによって公開されている UNIX ソケットの 1 つに接続します。まず、JAR ファイルの 1 つを変更し、悪意のあるコードを挿入する必要があります。

ソケット クライアントの作成

最初のステップは、「nac_server」の抽象 UNIX ソケットの 1 つに接続するためのバイトコードを生成することです。この例では、「supercmdlocalsocket」UNIX ソケットの使用を選択しました。まず、図 16 のような Java クラスを作成します。

図 16
図 16: 「supercmdlocalsocket」抽象 UNIX ソケットに接続するために Java で記述された「run()」メソッド

次に、このクラスをコンパイルし、クラスを DEX バイトコードに変換してから、「smali」を使用して逆アセンブルします。次に、この機能を配置する適切な場所を見つけます。

フックの挿入

Idea Friend アプリの静的解析と動的解析を行った結果、Idea Friend アプリは、ファイルに含まれるクラス「cn.com.xy.sms.sdk.Iservice.ParseUtilBubble」のメソッド「getBubbleViewVersion(..)」を実行したことが判明しました。アプリケーション起動時のJAR「parseUtilBubble_8.jar」。これを知って、悪意のあるコードをこのクラスに追加し、「getBubbleViewVersion(..)」メソッドにフックを挿入します (図 17 と図 18 参照)。

図 17
図17:「getBubbleViewVersion(..)」をフックして悪意のあるコードを呼び出す
図 18
図 18: 「supercmdlocalsocket」に接続するために逆アセンブルされた Dalvik で記述された「run()」メソッド

次に、前述のプロセスの手順 3 ~ 8 を実行して、新しい ELF を生成し、変更したバックアップを復元します。あとは、「nac_server」バイナリによって実行される悪意のあるペイロードをステージングするだけです。

バックアップの悪用パート 2: ペイロードのステージング (CVE-2017-3750)

Idea Friend アプリケーションが「nac_server」UNIX ソケットと通信できることはわかっていますが、残念ながら Idea Friend アプリケーションは、「nac_server」バイナリによってチェックされるホワイトリストに含まれていません。これは、ペイロードをステージングするための 2 つ目のアプリケーションを見つける必要があることを意味します。 「nac_server」のホワイトリスト (図 5) にあるアプリケーションのリストを、ローカル バックアップを許可するアプリケーションと比較することで、いくつかの潜在的なターゲットを特定できます。 Lenovo Security アプリケーション (「com.lenovo.security」) をターゲットとして使用します。

まず、「バックアップの悪用パート 1: コードの実行」セクションで説明されているプロセスに従って、Lenovo Security アプリケーションのローカル バックアップを生成します。次に、バックアップを変更して、図 19 に示す「go.sh」シェル スクリプトを含めます。「go.sh」スクリプトは、実行時に TCP ポート 1234 で telnet サーバーを起動するだけです。

図 19
図 19: 「go.sh」の内容

バックアップを再パッケージ化して復元した後、「ls」を使用して、ファイルがデバイスに正常にプッシュされたことを確認できます。

図 20
図 20: 「go.sh」を Lenovo Security アプリケーションに正常にプッシュ

脆弱性の連鎖

一連の脆弱性をマッピングしたので、次の手順でエクスプロイトをトリガーできます。

  1. 設定アプリを起動し、アイデアフレンドアプリのアプリデータを消去してください。これにより、すでに存在する可能性のある正当な OAT バイナリが削除されます。
  2. Lenovo Security アプリケーションのローカル バックアップを作成します。
  3. 「go.sh」ペイロードが含まれるようにローカル バックアップを変更します。
  4. 変更したバックアップをデバイスに復元します。
  5. Idea Friend アプリケーションのローカル バックアップを作成します。
  6. ローカル バックアップを変更して、悪意のある OAT バイナリを含めます。
  7. 変更したバックアップをデバイスに復元します。
  8. アイデア フレンド アプリケーションを起動します。 OAT バイナリが既に存在する (そして有効に見える) ため、アプリケーションはコードを実行します。これにより、Idea Friend アプリケーションが「nac_server」によって公開された UNIX ソケットに接続され、ステージングされたペイロード「go.sh」のファイル パスが渡されます。次に、「nac_server」がペイロードを実行し、telnetd サーバーを起動します。
  9. telnet 接続を使用してデバイスに接続します。

図 21 はこのプロセスを示しており、コマンド「id」の出力を示しています。これは、「root_channel」の SEAndroid コンテキストを使用して、ユーザー「root」としてコードを実行していることを示しています。

図 21
図 21: UID「root」および「root_channel」として実行中の SEAndroid コンテキスト

結論

プラットフォーム開発者は、抽象的な UNIX ソケットを使用して機密性の高い機能を公開する場合は注意が必要です。代わりに、適切なファイルシステム権限と SEAndroid ポリシーを備えたファイルベースの UNIX ソケットを、権限のあるAndroid システム サービスと組み合わせて使用し、より構造化された安全なモデルを作成します。フォローアップ分析に基づいて、これは Motorola が使用することを決定したモデルです。

さらに、特権アプリケーションのバックアップを許可することも有害である可能性があるため、禁止する必要があります。アプリケーションが「android.uid.system」などの特権 Android ユーザー ID として実行されていないからといって、脆弱性を導入したり、特権の昇格に使用したりできないという意味ではありません。最後に、アプリケーションは、バックアップ内で実行可能コード (Java クラス、ELF バイナリ、または共有オブジェクト) を許可しないようにする必要があります。これは、 BackupAgentを使用して制限できます。

.resource-body li {
word-wrap: break-word;
}
.figure {
font-size: 12px;
}

参照: https://www.mandiant.com/resources/blog/back-app-gaining-root-lenovo-vibe

コメント

タイトルとURLをコピーしました