意圖重新導向
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
OWASP 類別:MASVS-PLATFORM:平台互動
總覽
發生意圖重新導向的情況,是指攻擊者可以部分或完整地控管某個意圖的內容,將該意圖用於在含有安全漏洞的應用程式環境中啟動新元件。
用於啟動新元件的意圖可透過多種方式提供,最常見的是在 extras
欄位中以序列化意圖的形式呈現,或是組合成字串並加以剖析。此外,控制部分參數也可能會導致相同結果。
影響
影響可能因情況而異。攻擊者可能會在含有安全漏洞的應用程式中執行內部功能,也可能會存取未匯出的 ContentProvider 物件等私人元件。
因應措施
一般
一般而言,請勿公開與重新導向巢狀意圖相關的功能。在無法避免的情況下,請採用下列因應方式:
應用程式可以使用 ResolveActivity
等方法,檢查意圖重新導向的位置:
Kotlin
val intent = getIntent()
// Get the component name of the nested intent.
val forward = intent.getParcelableExtra<Parcelable>("key") as Intent
val name: 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
Intent intent = getIntent()
// Get the component name of the nested intent.
Intent forward = (Intent) intent.getParcelableExtra("key");
ComponentName name = 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 時採用類似以下的邏輯:
Kotlin
val intent = IntentSanitizer.Builder()
.allowComponent("com.example.ActivityA")
.allowData("com.example")
.allowType("text/plain")
.build()
.sanitizeByThrowing(intent)
Java
Intent intent = new IntentSanitizer.Builder()
.allowComponent("com.example.ActivityA")
.allowData("com.example")
.allowType("text/plain")
.build()
.sanitizeByThrowing(intent);
常見錯誤
- 檢查
getCallingActivity()
是否傳回非空值。惡意應用程式可以為這個函式提供空值。
- 假設
checkCallingPermission()
適用於所有情況,或者該方法會在實際傳回整數時擲回例外狀況。
偵錯功能
如果應用程式指定 Android 12 (API 級別 31) 以上版本,您可以啟用偵錯功能。在某些情況下,這項功能可協助您偵測應用程式是否以不安全的方式啟動意圖。
如果應用程式同時執行下列這兩項動作,系統會偵測到不安全的意圖啟動作業,StrictMode
違規情形也會隨之發生:
- 應用程式將巢狀意圖從已傳遞意圖的額外項目中拆解出來。
- 應用程式立即使用該巢狀意圖啟動某個應用程式元件,例如將意圖傳遞至
startActivity()
、startService()
或 bindService()
。
資源
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- 待處理意圖
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2024-01-05 (世界標準時間)。
[null,null,["上次更新時間:2024-01-05 (世界標準時間)。"],[],[],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)"]]