OWASP カテゴリ: MASVS-CODE: コード品質
概要
カスタム権限に関連するリスクは、カスタム権限の定義が欠落しているかスペルが間違っている場合、または対応する android:protectionLevel 属性がマニフェスト内で誤用されている場合に発生します。
たとえば、同じ名前のカスタム権限を作成し、悪意のあるアプリによって定義され、異なる保護レベルが適用されている場合、これらのリスクが悪用される可能性があります。
カスタム権限は、他のアプリとリソースや機能を共有できるように設計されています。カスタム権限の正当な使用例としては、次のようなものがあります。
- 2 つ以上のアプリ間のプロセス間通信(IPC)の制御
- サードパーティ サービスへのアクセス
- アプリの共有データへのアクセスの制限
影響
この脆弱性が悪用されると、悪意のあるアプリが本来保護されるべきリソースにアクセスできるようになります。この脆弱性の影響は、保護対象のリソースと、元のアプリ サービスに関連付けられた権限によって異なります。
リスク: カスタム権限のスペルミス
カスタム権限はマニフェストで宣言できますが、スペルミスが原因で、エクスポートされた Android コンポーネントの保護に別のカスタム権限が使用されることがあります。悪意のあるアプリは、権限のスペルを間違えたアプリを次のいずれかの方法で悪用できます。
- その権限を最初に登録する
- 後続のアプリでスペルを予測する
これにより、アプリがリソースへの不正なアクセスや、被害者のアプリの制御を行う可能性があります。
たとえば、脆弱なアプリが READ_CONTACTS 権限を使用してコンポーネントを保護しようとしたときに、誤って権限を READ_CONACTS とスペルミスしたとします。悪意のあるアプリは、どのアプリ(またはシステム)にも所有されていないため、READ_CONACTS を要求して、保護されたコンポーネントにアクセスできます。 この脆弱性のもう 1 つの一般的なバリアントは android:permission=True です。大文字と小文字に関係なく、true や false などの値は権限宣言の無効な入力であり、他のカスタム権限宣言のスペルミスと同様に扱われます。これを修正するには、android:permission 属性の値を有効な権限文字列に変更する必要があります。たとえば、アプリがユーザーの連絡先にアクセスする必要がある場合、android:permission 属性の値は android.permission.READ_CONTACTS にする必要があります。
リスクの軽減
Android lint チェック
カスタム権限を宣言するときは、Android lint チェックを使用して、コードのスペルミスやその他の潜在的なエラーを見つけます。
命名規則
一貫した命名規則を使用して、スペルミスを目立たせます。アプリのマニフェストでカスタム権限の宣言にスペルミスがないか慎重に確認してください。
リスク: 孤立した権限
権限は、アプリのリソースを保護するために使用されます。アプリがリソースへのアクセスに必要な権限を宣言できる場所は 2 つあります。
- AndroidManifest.xml: AndroidManifest.xml ファイルで事前定義されています(指定しない場合は、
<application>権限が使用されます)。例: プロバイダ 権限、レシーバ権限、アクティビティ権限、サービス 権限。 - コード: ランタイム コードに登録されています。例:
registerReceiver()。
ただし、これらの権限は、デバイス上の APK のマニフェストに対応する
<permission> タグで定義されていない場合があります。この場合、孤立した権限 と呼ばれます。この状況は、次のようなさまざまな理由で発生する可能性があります。
- マニフェストの更新と権限チェックを含むコードの間に同期のずれがある
- 権限を含む APK がビルドに含まれていないか、間違ったバージョンが含まれている
- チェックまたはマニフェストの権限名のスペルが間違っている
悪意のあるアプリは、孤立した権限を定義して取得する可能性があります。この場合、孤立した権限を信頼してコンポーネントを保護する権限付きアプリが侵害される可能性があります。
権限付きアプリが権限を使用してコンポーネントを保護または制限している場合、悪意のあるアプリがそのコンポーネントにアクセスできるようになります。例としては、権限で保護されたアクティビティの起動、コンテンツ プロバイダへのアクセス、孤立した権限で保護されたブロードキャスト レシーバへのブロードキャストなどがあります。
また、権限付きアプリが、悪意のあるアプリを正当なアプリであると誤認して、ファイルやコンテンツを読み込む状況が発生する可能性もあります。
リスクの軽減
アプリがコンポーネントの保護に使用するカスタム権限はすべて、マニフェストでも定義されていることを確認してください。
アプリは、コンテンツ プロバイダへのアクセスを保護するために、カスタム権限 my.app.provider.READ と my.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 または Dangerous の保護レベルを避ける
権限に normal または dangerous protectionLevel を使用すると、ほとんどのアプリが権限をリクエストして取得できます。
- 「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)が原因です。
これが、カスタム権限よりも署名チェックが推奨される理由の 1 つです(競合状態のリスクもあります)。
リスク: 競合状態
正当なアプリ A が、他の X アプリで使用される署名カスタム権限を定義しているが、その後アンインストールされた場合、悪意のあるアプリ B は、異なる protectionLevel(たとえば normal)で同じカスタム権限を定義できます。 このようにして、B は、アプリ A と同じ証明書で署名する必要なく、X アプリのそのカスタム権限で保護されたすべてのコンポーネントにアクセスできます。
B が A より先にインストールされた場合も同様です。
リスクの軽減
コンポーネントを提供元アプリと同じ署名で署名されたアプリでのみ使用できるようにする場合は、そのコンポーネントへのアクセスを制限するカスタム権限を定義せずに済ませることができます。この場合は、署名チェックを使用できます。アプリの 1 つが別のアプリにリクエストを行うと、2 番目のアプリは、リクエストに応じる前に両方のアプリが同じ証明書で署名されていることを確認できます。
リソース
- 権限リクエストを最小限に抑える
- 権限の概要
- 保護レベルの説明
- CustomPermissionTypo Android Lint
- Android Lint の使用方法
- Android 権限の詳細な説明と興味深いファズテストの結果を記載した調査論文