عمليات بث ثابتة
تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
فئة OWASP: MASVS-PLATFORM: Platform Interaction (التفاعل مع النظام الأساسي)
نظرة عامة
يمكن لتطبيقات Android ونظام Android استخدام عمليات البث كنظام مراسلة لإشعار التطبيقات الأخرى بالأحداث التي قد تهمّها. البثّات الثابتة هي نوع خاص من البثّات التي تبقى عناصر النية المُرسَلة فيها في ذاكرة التخزين المؤقت بعد اكتمال البثّ. قد يعيد النظام بثّ النوايا الثابتة في عمليات التسجيل اللاحقة لأجهزة الاستقبال. تواجه واجهة برمجة التطبيقات لميزة "البثّات الثابتة" عددًا من العيوب المتعلّقة بالأمان، لذلك تم إيقافها نهائيًا في الإصدار 5.0 من نظام التشغيل Android (المستوى 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()
إلى جهاز استقبال واحد في المرة الواحدة للسماح لأجهزة الاستقبال ذات الأولوية الأعلى باستهلاك البث قبل تسليمه إلى أجهزة الاستقبال ذات الأولوية الأقل. أثناء تنفيذ كل جهاز استقبال بدوره، يمكنه نشر نتيجة إلى جهاز الاستقبال التالي، مثلاً من خلال استدعاء setResultData()
، أو يمكنه إيقاف البث، ما يمنع أجهزة الاستقبال اللاحقة من تلقّي البث. يمكن للمهاجم الذي يمكنه تلقّي عمليات البث المستمرة من تطبيق شرعي إنشاء جهاز استقبال ذو أولوية عالية للتلاعب ببيانات نتائج البث أو إيقاف عمليات البث تمامًا.
التأثير
يختلف التأثير حسب طريقة استخدام عمليات البث الثابتة والبيانات التي يتم تمريرها إلى أجهزة استقبال البث. بشكل عام، يمكن أن يؤدي استخدام عمليات البث الثابتة إلى تعريض البيانات الحسّاسة للخطر والتلاعب بالبيانات والوصول غير المصرّح به لتنفيذ السلوك في تطبيق آخر ورفض الخدمة.
إجراءات التخفيف
يجب عدم استخدام البثّات الثابتة. النمط المقترَح هو استخدام عمليات البث غير الثابتة مع آلية أخرى، مثل قاعدة بيانات محلية، لاسترداد القيمة الحالية متى شئت.
يمكن للمطوّرين التحكّم في المستخدمين الذين يمكنهم تلقّي عمليات البث غير الثابتة باستخدام الأذونات أو من خلال ضبط اسم حِزمة التطبيق في النية. بالإضافة إلى ذلك، إذا لم يكن من الضروري إرسال بث إلى مكوّنات خارج التطبيق، استخدِم LiveData
الذي ينفِّذ نمط المراقِب.
يمكنك الاطّلاع على مزيد من المعلومات حول تأمين البث في صفحة نظرة عامة على البث.
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-07-26 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-07-26 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],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."]]