スティッキー ブロードキャスト
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
OWASP カテゴリ: MASVS-PLATFORM: プラットフォームのインタラクション
概要
Android アプリと Android システムは、ブロードキャストをメッセージ システムとして使用し、他のアプリに関係がありそうなイベントをそれらのアプリに通知できます。スティッキー ブロードキャストとは、ブロードキャストの完了後も、送信されたインテント オブジェクトがキャッシュに残る特別なタイプのブロードキャストです。システムは、スティッキー インテントをその後のレシーバ登録に再ブロードキャストできます。残念ながら、スティッキー ブロードキャスト API にはセキュリティに関する欠点がいくつかあります。Android 5.0(API レベル 21)で非推奨になったのは、それが理由です。
誰でもスティッキー ブロードキャストにアクセスできる
スティッキー ブロードキャストは、特定の権限を保持するレシーバに限定することができません。したがって、機密情報のブロードキャストには適していません。次のようにブロードキャスト Intent
でアプリのパッケージ名を指定すると、BroadcastReceivers
のセットが制限されると考えたくなるかもしれません。
Kotlin
val intent = Intent("com.example.NOTIFY").apply {
setPackage("com.example.myapp")
}
applicationContext.sendBroadcast(intent)
Java
Intent intent = new Intent("com.example.NOTIFY");
intent.setPackage("com.example.myapp");
getApplicationContext().sendBroadcast(intent);
この例では、ブロードキャストが送信されたとき、com.example.myapp
パッケージ内のレシーバのみがインテントを受信します。しかし、インテントがスティッキー キャッシュから再ブロードキャストされるとき、パッケージ名フィルタは適用されません。registerReceiver()
メソッドを使用してレシーバを登録する際は、レシーバが属するパッケージの名前は考慮されずに、指定されたフィルタに一致するスティッキー キャッシュ内のすべてのインテントがレシーバに再ブロードキャストされます。
誰でもスティッキー ブロードキャストを送信できる
アプリがスティッキー ブロードキャストを送信するために必要な権限は android.permission.BROADCAST_STICKY
だけであり、この権限はアプリのインストール時に自動的に付与されます。したがって、攻撃者は任意のレシーバに任意のインテントを送信することができ、別のアプリに対する不正なアクセス権を取得する可能性があります。ブロードキャスト レシーバは、送信元を特定の権限を保持するもののみに制限できます。しかし、そのようにすると、レシーバはスティッキー キャッシュからブロードキャストを受信できなくなります。それらは、送信される際にアプリの識別子に関するコンテキストがなく、権限付きでブロードキャストされないからです。
誰でもスティッキー ブロードキャストを変更できる
インテントがスティッキー ブロードキャストの一部である場合、スティッキー キャッシュ内の同じアクション、データ、型、識別子、クラス、カテゴリを持つ以前のインスタンスは、すべてそのインテントに置き換えられます。したがって、攻撃者は正当なアプリから送信されるスティッキー インテントの追加データを簡単に上書きすることができ、そのデータが他のレシーバに再ブロードキャストされる可能性があります。
sendStickyOrderedBroadcast()
メソッドを使用して送信されたブロードキャストは一度に 1 つのレシーバに配信されるため、優先度の高いレシーバは、より優先度の低いレシーバにブロードキャストが配信される前にそれを消費できます。各レシーバは順番に実行されるので、setResultData()
の呼び出しなどにより、結果を次のレシーバに伝播できます。または、ブロードキャストを中止して、後続のレシーバがブロードキャストを受信できないようにすることもできます。正当なアプリからの順序付けされたスティッキー ブロードキャストを受信できる攻撃者は、優先度の高いレシーバを作成して、ブロードキャスト結果データを改ざんしたり、ブロードキャストを完全に破棄したりできます。
影響
影響は、スティッキー ブロードキャストが使用される方法と、ブロードキャスト レシーバに渡されるデータの内容によって異なります。一般的に、スティッキー ブロードキャストを使用すると、機密データの開示、データの改ざん、別のアプリで動作を実行するための不正なアクセス、サービス拒否を招くおそれがあります。
リスクの軽減
スティッキー ブロードキャストを使用しないでください。ローカル データベースのような別のメカニズムで非スティッキー ブロードキャストを使用し、必要なときに現在の値を取得するパターンをおすすめします。
デベロッパーは、権限を使用するか、インテントにアプリのパッケージ名を設定することにより、誰が非スティッキー ブロードキャストを受信するかを制御できます。さらに、アプリ外のコンポーネントにブロードキャストを送信する必要がない場合は、オブザーバー パターンを実装する LiveData
を使用します。
ブロードキャストのセキュリティ保護について詳しくは、ブロードキャストの概要ページをご覧ください。
このページのコンテンツやコードサンプルは、コンテンツ ライセンスに記載のライセンスに従います。Java および OpenJDK は Oracle および関連会社の商標または登録商標です。
最終更新日 2024-02-23 UTC。
[null,null,["最終更新日 2024-02-23 UTC。"],[],[],null,["# Sticky Broadcasts\n\n\u003cbr /\u003e\n\n**OWASP category:** [MASVS-PLATFORM: Platform Interaction](https://mas.owasp.org/MASVS/09-MASVS-PLATFORM)\n\nOverview\n--------\n\nAndroid apps and the Android system can use broadcasts as a messaging system to notify other apps of events that they might be interested in. *Sticky broadcasts* are a special type of broadcast for which the sent intent object(s) remains in the cache after the broadcast is complete. The system may re-broadcast sticky intents to later registrations of receivers. Unfortunately, the sticky broadcasts API suffers from a number of security-related shortcomings, which is why it was deprecated in Android 5.0 (API level 21).\n\n### Anyone can access sticky broadcasts\n\nSticky broadcasts cannot be restricted to receivers that hold certain permissions. Therefore, they aren't suitable for broadcasting sensitive information. It might be tempting to think that specifying the [application package name](/reference/android/content/Intent#setPackage(java.lang.String)) on the broadcast `Intent` limits the set of `BroadcastReceivers`: \n\n### Kotlin\n\n val intent = Intent(\"com.example.NOTIFY\").apply {\n setPackage(\"com.example.myapp\")\n }\n applicationContext.sendBroadcast(intent)\n\n### Java\n\n Intent intent = new Intent(\"com.example.NOTIFY\");\n intent.setPackage(\"com.example.myapp\");\n getApplicationContext().sendBroadcast(intent);\n\nIn the example, only receivers in the `com.example.myapp` package receive the intent when the broadcast is sent. However, the package name filter isn't applied when the Intent is re-broadcast from the sticky cache. When registering a receiver using the [`registerReceiver()`](/reference/android/content/Context#registerReceiver(android.content.BroadcastReceiver,%20android.content.IntentFilter)) method, all intents in the sticky cache that match the specified filter are re-broadcast to the receiver regardless of the package name in which the receiver resides.\n\n### Anyone can send sticky broadcasts\n\nTo send sticky broadcasts, an app only requires the `android.permission.BROADCAST_STICKY` permission, which is granted automatically when the app is installed. Therefore, attackers can send any intent to any receiver, potentially gaining unauthorized access to another app. Broadcast receivers can restrict the senders to those holding a certain permission. However, by doing so, the receiver can't receive broadcasts from the sticky cache because those are not sent in the context of any app's identity and aren't broadcast with any permissions.\n\n### Anyone can modify sticky broadcasts\n\nWhen an intent is part of a sticky broadcast, that intent replaces any previous instance that has the same action, data, type, identifier, class, and categories in the sticky cache. Therefore, an attacker can trivially overwrite the extra data in a sticky intent from a legitimate app, which might then get re-broadcast to other receivers.\n\nBroadcasts sent using the [`sendStickyOrderedBroadcast()`](/reference/android/content/Context#sendStickyOrderedBroadcast(android.content.Intent,%20android.content.BroadcastReceiver,%20android.os.Handler,%20int,%20java.lang.String,%20android.os.Bundle)) method are delivered to one receiver at a time to allow receivers with higher priority to consume the broadcast before it's delivered to receivers with lower priority. As each receiver executes in turn, it can propagate a result to the next receiver, such as by calling [`setResultData()`](/reference/android/content/BroadcastReceiver#setResultData(java.lang.String)), or it can [abort the broadcast](/reference/android/content/BroadcastReceiver#abortBroadcast()), preventing subsequent receivers from receiving the broadcast. An attacker that can receive sticky ordered broadcasts from a legitimate app can create a high-priority receiver to tamper with the broadcast result data or drop broadcasts completely.\n\nImpact\n------\n\nImpact varies depending on how sticky broadcasts are used and what data is passed to the broadcast receivers. Generally speaking, use of sticky broadcasts can lead to sensitive data exposure, data tampering, unauthorized access to execute behavior in another app, and denial of service.\n\nMitigations\n-----------\n\nSticky broadcasts shouldn't be used. The recommended pattern is to use non-sticky broadcasts with another mechanism, such as a local database, to retrieve the current value whenever desired.\n\nDevelopers can control who can receive non-sticky broadcasts using [permissions](/guide/components/broadcasts#restrict-broadcasts-permissions) or by setting the [application package name](/reference/android/content/Intent#setPackage(java.lang.String)) on the intent. Furthermore, if a broadcast doesn't need to be sent to components outside of an app, use [`LiveData`](/reference/androidx/lifecycle/LiveData), which implements the [observer pattern](https://en.wikipedia.org/wiki/Observer_pattern).\n\nMore information about securing broadcasts can be found on the [broadcasts overview](/guide/components/broadcasts#security-and-best-practices) page."]]