カスタム権限

OWASP カテゴリ: MASVS-CODE: コード品質

概要

カスタム権限に関連するリスクは、カスタム権限の定義が存在しないかスペルが間違っている場合、または対応する android:protectionLevel 属性がマニフェスト内で誤用されている場合に発生します。

たとえば、同じ名前のカスタム権限を作成して、悪意のあるアプリによって定義され、異なる保護レベルが適用されたカスタム権限を作成することで、これらのリスクを悪用できます。

カスタム権限は、他のアプリとリソースや機能を共有できるように設計されています。カスタム権限の正当な使用例としては、次のものがあります。

  • 複数のアプリ間のプロセス間通信(IPC)を制御する
  • サードパーティ サービスへのアクセス
  • アプリの共有データへのアクセスを制限する

影響

この脆弱性が悪用されると、悪意のあるアプリが本来保護対象であるリソースにアクセスできるようになります。脆弱性の影響は、保護されているリソースと元のアプリケーション サービスの関連する権限によって異なります。

リスク: カスタム権限の入力ミス

カスタム権限がマニフェストで宣言されているが、誤字脱字が原因で、エクスポートされた Android コンポーネントの保護に別のカスタム権限が使用されている。悪意のあるアプリは、次のいずれかの方法で、権限のスペルを間違えたアプリを悪用できます。

  • 最初にその権限を登録する
  • 後続の申請でのスペルの予測

これにより、アプリがリソースへの不正アクセスや被害を受けたアプリの制御を許可される可能性があります。

たとえば、脆弱なアプリが権限 READ_CONTACTS を使用してコンポーネントを保護しようとしているが、誤って権限を READ_CONACTS と誤って入力している場合。悪意のあるアプリは、READ_CONACTS をアプリ(またはシステム)が所有していないため、READ_CONACTS を宣言し、保護されたコンポーネントにアクセスできます。この脆弱性の別の一般的なバリアントは android:permission=True です。truefalse などの値は、大文字小文字に関係なく、権限宣言の無効な入力であり、他のカスタム権限宣言のスペルミスと同様に扱われます。これを修正するには、android:permission 属性の値を有効な権限文字列に変更する必要があります。たとえば、アプリがユーザーの連絡先にアクセスする必要がある場合、android:permission 属性の値は android.permission.READ_CONTACTS にする必要があります。

リスクの軽減

Android Lint チェック

カスタム権限を宣言する際は、Android lint チェックを使用して、コードの入力ミスなどの潜在的なエラーを検出します。

命名規則

一貫した命名規則を使用して、スペルミスを目立たせます。アプリのマニフェストでカスタム権限の宣言に入力ミスがないか慎重に確認してください。


リスク: 孤立した権限

権限は、アプリのリソースを保護するために使用されます。アプリがリソースへのアクセスに必要な権限を宣言できる場所は 2 つあります。

ただし、これらの権限が、デバイス上の APK のマニフェスト内の対応する <permission> タグで定義されていない場合があります。この場合、それらは孤立した権限と呼ばれます。この状況は、次のような理由で発生することがあります。

  • マニフェストの更新と、権限チェックを含むコードの更新が同期されていない可能性があります。
  • 権限を含む APK がビルドに含まれていない、または間違ったバージョンが含まれている
  • チェックまたはマニフェストの権限名のスペルが間違っている

悪意のあるアプリは、孤立した権限を定義して取得する可能性があります。この場合、コンポーネントを保護するために孤立した権限を信頼する特権アプリが侵害される可能性があります。

特権アプリが権限を使用してコンポーネントを保護または制限している場合、悪意のあるアプリにそのコンポーネントへのアクセス権が付与される可能性があります。たとえば、権限で保護されたアクティビティの起動、コンテンツ プロバイダへのアクセス、孤立した権限で保護されたブロードキャスト レシーバへのブロードキャストなどです。

また、特権アプリが悪意のあるアプリを正規のアプリと誤認し、ファイルやコンテンツを読み込む状況も発生する可能性があります。

リスクの軽減

アプリがコンポーネントの保護に使用するすべてのカスタム権限が、マニフェストでも定義されていることを確認します。

アプリは、カスタム権限 my.app.provider.READmy.app.provider.WRITE を使用して、コンテンツ プロバイダへのアクセスを保護します。

XML

<provider android:name="my.app.database.CommonContentProvider" android:readPermission="my.app.provider.READ" android:writePermission="my.app.provider.WRITE" android:exported="true" android:process=":myappservice" android:authorities="my.app.database.contentprovider"/>

また、アプリはこれらのカスタム権限を定義して使用するため、他の悪意のあるアプリが使用できないようにします。

XML

<permission android:name="my.app.provider.READ"/>
<permission android:name="my.app.provider.WRITE"/>
<uses-permission android:name="my.app.provider.READ" />
<uses-permission android:name="my.app.provider.WRITE" />

リスク: android:protectionLevel の誤用

この属性は、権限に潜在的なリスクレベルを記述し、権限を付与するかどうかを決定する際にシステムが従う必要がある手順を示します。

リスクの軽減

正常または危険な保護レベルを回避する

権限に normal または dangerousprotectionLevel を使用すると、ほとんどのアプリが権限をリクエストして取得できます。

  • 「normal」の場合、宣言のみが必要です
  • 「dangerous」は多くのユーザーに承認される

したがって、これらの protectionLevels はほとんどセキュリティを提供しません。

署名権限を使用する(Android 10 以降)

可能な限り、署名保護レベルを使用します。この機能を使用すると、権限を作成したアプリと同じ証明書で署名された他のアプリのみが、保護された機能にアクセスできるようになります。専用の(再利用されていない)署名証明書を使用していて、それをキーストアに安全に保存していることを確認します。

マニフェストで次のようにカスタム権限を定義します。

XML

<permission
    android:name="my.custom.permission.MY_PERMISSION"
    android:protectionLevel="signature"/>

次のように、アクティビティなどのアクセスを、このカスタム権限が付与されているアプリのみに制限します。

XML

<activity android:name=".MyActivity" android:permission="my.custom.permission.MY_PERMISSION"/>

このカスタム権限を宣言したアプリと同じ証明書で署名された他のアプリには、.MyActivity アクティビティへのアクセス権が付与されます。この権限は、マニフェストで次のように宣言する必要があります。

XML

<uses-permission android:name="my.custom.permission.MY_PERMISSION" />

署名カスタム権限に注意(Android 10 以前)

アプリの対象が Android 10 未満の場合、アンインストールやアップデートによってアプリのカスタム パーミッションが削除されると、悪意のあるアプリがそれらのカスタム パーミッションを使い続け、チェックを回避する可能性があります。これは、Android 10 で修正された権限昇格の脆弱性(CVE-2019-2200)が原因です。

これは、カスタム権限よりも署名チェックが推奨される理由の一つで、競合状態のリスクも伴います。


リスク: 競合状態

正当なアプリ A が、他の X アプリで使用される署名カスタム権限を定義し、その後アンインストールされた場合、悪意のあるアプリ B は、同じカスタム権限を別の protectionLevelnormal など)で定義できます。このようにして、B は、アプリの A と同じ証明書で署名しなくても、X アプリのカスタム権限で保護されているすべてのコンポーネントにアクセスできます。

A より前に B がインストールされている場合も同じです。

リスクの軽減

コンポーネントを、提供元アプリと同じ署名で署名されたアプリでのみ使用できるようにする場合は、そのコンポーネントへのアクセスを制限するカスタム権限を定義せずに済ませることができます。この場合は、署名チェックを使用できます。いずれかのアプリが別のアプリのリクエストを行うと、2 つ目のアプリはリクエストに応える前に両方のアプリが同じ証明書で署名されていることを確認できます。


リソース