تحدث إعادة توجيه النية عندما يتمكّن المهاجم من التحكّم جزئيًا أو كليًا في محتويات نية مستخدَمة لتشغيل مكوّن جديد في سياق تطبيق متوفّر فيه ثغرة أمنية.
يمكن تقديم النية المستخدَمة لإطلاق المكوّن الجديد بعدة طرق،
ويكون الأكثر شيوعًا إما نية مُسلسلة في حقل extras أو نية تم تجميعها
في سلسلة وتحليلها. يمكن أن يؤدي التحكّم الجزئي في المَعلمات أيضًا إلى النتيجة
نفسها.
التأثير
وقد يختلف التأثير. يمكن للمهاجم تنفيذ ميزات داخلية في
التطبيق المعرض للاختراق، أو يمكنه الوصول إلى مكوّنات خاصة مثل عناصر
ContentProvider التي لم يتم تصديرها.
إجراءات التخفيف
بشكل عام، لا تعرض الميزات ذات الصلة بإعادة توجيه النوايا المُدمَجة. في الحالات التي لا يمكن فيها تجنُّب استخدام هذه التقنيات، يُرجى تطبيق أساليب التخفيف التالية:
يجب إزالة أي معلومات غير ضرورية من الحِزمة. من المهم التحقق من العلامات
أو إزالتها (FLAG_GRANT_READ_URI_PERMISSION,
FLAG_GRANT_WRITE_URI_PERMISSION, FLAG_GRANT_PERSISTABLE_URI_PERMISSION, and
FLAG_GRANT_PREFIX_URI_PERMISSION)، والتحقّق من مكان إعادة توجيه الطلب. يمكن لفريق IntentSanitizer مساعدتك في هذه العملية.
استخدِم عناصر PendingIntent. ويؤدي ذلك إلى منع تصدير المكوّن ويجعل نية الإجراء المستهدَف غير قابلة للتغيير.
يمكن للتطبيقات التحقّق من المكان الذي تتم إعادة توجيه النية إليه باستخدام طرق مثل methods
ResolveActivity:
Kotlin
valintent=getIntent()// Get the component name of the nested intent.valforward=intent.getParcelableExtra<Parcelable>("key")asIntentvalname:ComponentName=forward.resolveActivity(packageManager)// Check that the package name and class name contain the expected values.if(name.packagename=="safe_package" && name.className=="safe_class"){// Redirect the nested intent.startActivity(forward)}
Java
Intentintent=getIntent()// Get the component name of the nested intent.Intentforward=(Intent)intent.getParcelableExtra("key");ComponentNamename=forward.resolveActivity(getPackageManager());// Check that the package name and class name contain the expected values.if(name.getPackageName().equals("safe_package")&&
name.getClassName().equals("safe_class")){// Redirect the nested intent.startActivity(forward);}
يمكن للتطبيقات استخدام IntentSanitizer باستخدام منطق مشابه مما يلي:
يقدّم نظام التشغيل Android 16 حلّاً لتعزيز الأمان بشكل تلقائي من أجل Intent
منع عمليات استغلال إعادة التوجيه. في معظم الحالات، لن تواجه التطبيقات التي تستخدم النوايا عادةً
أي مشاكل في التوافق.
إيقاف معالجة إعادة التوجيه المستندة إلى النيّة
يقدّم نظام التشغيل Android 16 واجهة برمجة تطبيقات جديدة تتيح للتطبيقات إيقاف ميزات
الحماية الأمنية عند التشغيل. قد يكون ذلك ضروريًا في حالات معيّنة يتداخل فيها سلوك أمان الإعدادات التلقائية مع حالات الاستخدام المشروعة للتطبيق.
في Android 16، يمكنك إيقاف إجراءات الحماية الأمنية باستخدام الطريقة
removeLaunchSecurityProtection() على العنصر Intent. مثلاً:
vali=intentvaliSublevel:Intent? =i.getParcelableExtra("sub_intent")iSublevel?.removeLaunchSecurityProtection()// Opt out from hardeningiSublevel?.let{startActivity(it)}
أخطاء شائعة
التحقّق مما إذا كانت getCallingActivity() تعرِض قيمة غير فارغة يمكن للتطبيقات الضارّة
تقديم قيمة فارغة لهذه الدالة.
بافتراض أنّ checkCallingPermission() تعمل في جميع السياقات، أو أنّ المحاولة
تُعرِض استثناءً عندما تُعيد عددًا صحيحًا.
ميزات تصحيح الأخطاء
بالنسبة إلى التطبيقات التي تستهدف الإصدار 12 من نظام التشغيل Android (المستوى 31 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث، يمكنك تفعيل ميزة تصحيح الأخطاء التي تساعدك في بعض الحالات في رصد ما إذا كان تطبيقك يؤدي إلى بدء عملية غير آمنة لطلب.
إذا نفَّذ تطبيقك كلا الإجراءَين التاليَين، يرصد النظام
بدء تشغيل نية غير آمنة، وتحدث مخالفة StrictMode:
يُفكّ تطبيقك حزمة هدف مُدمَج من البيانات الإضافية لهدف تم إرساله.
يبدأ تطبيقك على الفور أحد مكوّنات التطبيق باستخدام هذا الإجراء المُدمَج، مثل
تمرير الإجراء إلى startActivity() أو startService() أو bindService().
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ 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,["# Intent redirection\n\n\u003cbr /\u003e\n\n**OWASP category:** [MASVS-PLATFORM: Platform Interaction](https://mas.owasp.org/MASVS/09-MASVS-PLATFORM)\n\nOverview\n--------\n\nAn intent redirection occurs when an attacker can partly or fully control the\ncontents of an intent used to launch a new component in the context of a\nvulnerable app.\n\nThe intent used to launch the new component can be supplied in several ways,\nmost commonly either as a serialized intent in an `extras` field, or marshaled\nto a string and parsed. Partial control of parameters can also lead to the same\nresult.\n\nImpact\n------\n\nThe impact can vary. An attacker might execute internal features in the\nvulnerable app, or it might access private components like unexported\nContentProvider objects.\n\nMitigations\n-----------\n\nIn general, don't expose features related to redirecting nested intents. In\ncases where it's unavoidable, apply the following mitigation methods:\n\n- Properly sanitize the bundled information. It's important to remember to check or clear flags (`FLAG_GRANT_READ_URI_PERMISSION,\n FLAG_GRANT_WRITE_URI_PERMISSION, FLAG_GRANT_PERSISTABLE_URI_PERMISSION, and\n FLAG_GRANT_PREFIX_URI_PERMISSION`), and to check where the intent is being redirected. [`IntentSanitizer`](/reference/kotlin/androidx/core/content/IntentSanitizer) can help with this process.\n- Use [`PendingIntent`](/guide/components/intents-filters#PendingIntent) objects. This prevents your component from being exported and makes the target action intent immutable.\n\nApps can check where an intent is being redirected using methods such as\n[`ResolveActivity`](/reference/android/content/Intent#resolveActivity(android.content.pm.PackageManager)): \n\n### Kotlin\n\n val intent = getIntent()\n // Get the component name of the nested intent.\n val forward = intent.getParcelableExtra\u003cParcelable\u003e(\"key\") as Intent\n val name: ComponentName = forward.resolveActivity(packageManager)\n // Check that the package name and class name contain the expected values.\n if (name.packagename == \"safe_package\" && name.className == \"safe_class\") {\n // Redirect the nested intent.\n startActivity(forward)\n }\n\n### Java\n\n Intent intent = getIntent()\n // Get the component name of the nested intent.\n Intent forward = (Intent) intent.getParcelableExtra(\"key\");\n ComponentName name = forward.resolveActivity(getPackageManager());\n // Check that the package name and class name contain the expected values.\n if (name.getPackageName().equals(\"safe_package\") &&\n name.getClassName().equals(\"safe_class\")) {\n // Redirect the nested intent.\n startActivity(forward);\n }\n\nApps can use [`IntentSanitizer`](/reference/kotlin/androidx/core/content/IntentSanitizer) using logic similar to the\nfollowing: \n\n### Kotlin\n\n val intent = IntentSanitizer.Builder()\n .allowComponent(\"com.example.ActivityA\")\n .allowData(\"com.example\")\n .allowType(\"text/plain\")\n .build()\n .sanitizeByThrowing(intent)\n\n### Java\n\n Intent intent = new IntentSanitizer.Builder()\n .allowComponent(\"com.example.ActivityA\")\n .allowData(\"com.example\")\n .allowType(\"text/plain\")\n .build()\n .sanitizeByThrowing(intent);\n\n#### Default protection\n\nAndroid 16 introduces a by-default security hardening solution to `Intent`\nredirection exploits. In most cases, apps that use intents normally won't\nexperience any compatibility issues.\n\n##### Opt out of Intent redirection handling\n\nAndroid 16 introduces a new API that allows apps to opt out of launch security\nprotections. This might be necessary in specific cases where the default\nsecurity behavior interferes with legitimate app use cases.\n| **Important:** Opting out of security protections should be done with caution and only when absolutely necessary, as it can increase the risk of security vulnerabilities. Carefully assess the potential impact on your app's security before using this API.\n\nIn Android 16, you can opt out of security protections by using the\n`removeLaunchSecurityProtection()` method on the `Intent` object. For example: \n\n val i = intent\n val iSublevel: Intent? = i.getParcelableExtra(\"sub_intent\")\n iSublevel?.removeLaunchSecurityProtection() // Opt out from hardening\n iSublevel?.let { startActivity(it) }\n\n#### Common mistakes\n\n- Checking if `getCallingActivity()` returns a non-null value. Malicious apps can supply a null value for this function.\n- Assuming that `checkCallingPermission()` works in all contexts, or that the method throws an exception when it is actually returning an integer.\n\n#### Debugging features\n\nFor apps that target Android 12 (API level 31) or higher, you can enable a\n[debugging feature](/guide/components/intents-filters#DetectUnsafeIntentLaunches) that, in some cases, helps you detect whether your app is\nperforming an unsafe launch of an intent.\n\nIf your app performs **both** of the following actions, the system detects an\nunsafe intent launch, and a `StrictMode` violation occurs:\n\n- Your app unparcels a nested intent from the extras of a delivered intent.\n- Your app immediately starts an app component using that nested intent, such as passing the intent into `startActivity()`, `startService()`, or `bindService()`.\n\nResources\n---------\n\n- [Remediation for Intent Redirection](https://support.google.com/faqs/answer/9267555)\n- [Intents and intent filters](/guide/components/intents-filters#DetectUnsafeIntentLaunches)"]]