Redirection des intents
Restez organisé à l'aide des collections
Enregistrez et classez les contenus selon vos préférences.
Catégorie OWASP : MASVS-PLATFORM : interaction avec la plate-forme
Présentation
Une redirection d'intent se produit lorsqu'un pirate informatique parvient à contrôler partiellement ou entièrement le contenu d'un intent utilisé pour lancer un nouveau composant dans le contexte d'une application vulnérable.
L'intent utilisé pour lancer le nouveau composant peut être fourni de plusieurs manières, le plus souvent en tant qu'intent sérialisé dans un champ extras
, ou organisé en chaîne et analysé. Le contrôle partiel des paramètres peut également conduire au même résultat.
Impact
L'impact peut varier. Un pirate informatique peut exécuter une fonctionnalité interne dans l'application vulnérable ou accéder à des composants privés tels que des objets ContentProvider non exportés.
Stratégies d'atténuation
Général
En général, n'exposez pas les fonctionnalités liées à la redirection des intents imbriqués. Si cela est inévitable, appliquez les méthodes d'atténuation suivantes :
- Nettoyez correctement les informations regroupées. Il est important de vérifier ou de supprimer les indicateurs (
GRANT_URI_PERMISSIONS
), et d'identifier où l'intent est redirigé. IntentSanitizer peut vous aider.
- Utilisez des objets
PendingIntent
. Cela empêchera l'exportation du composant et rendra l'intent d'action cible immuable.
Les applications peuvent vérifier où un intent est redirigé à l'aide de méthodes telles que 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);
}
Les applications peuvent utiliser IntentSanitizer avec une logique semblable à celle-ci :
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);
Erreurs courantes
- Vérifier si
getCallingActivity()
renvoie une valeur non nulle. Les applications malveillantes peuvent fournir une valeur nulle pour cette fonction.
- Supposer que
checkCallingPermission()
fonctionne dans tous les contextes ou que la méthode génère une exception lorsqu'elle renvoie un nombre entier.
Fonctionnalités de débogage
Pour les applications qui ciblent Android 12 (niveau d'API 31) ou une version ultérieure, vous pouvez activer une fonctionnalité de débogage qui, dans certains cas, permet de détecter si votre application effectue un lancement d'intent non sécurisé.
Si votre application effectue les deux actions suivantes, le système détecte un lancement d'intent non sécurisé, et une violation StrictMode
se produit :
- Votre application dissocie un intent imbriqué des extras d'un intent livré.
- Votre application démarre immédiatement un composant d'application à l'aide de cet intent imbriqué, par exemple en transmettant l'intent dans
startActivity()
, startService()
ou bindService()
.
Ressources
Recommandations personnalisées
Le contenu et les exemples de code de cette page sont soumis aux licences décrites dans la Licence de contenu. Java et OpenJDK sont des marques ou des marques déposées d'Oracle et/ou de ses sociétés affiliées.
Dernière mise à jour le 2023/12/08 (UTC).
[[["Facile à comprendre","easyToUnderstand","thumb-up"],["J'ai pu résoudre mon problème","solvedMyProblem","thumb-up"],["Autre","otherUp","thumb-up"]],[["Il n'y a pas l'information dont j'ai besoin","missingTheInformationINeed","thumb-down"],["Trop compliqué/Trop d'étapes","tooComplicatedTooManySteps","thumb-down"],["Obsolète","outOfDate","thumb-down"],["Problème de traduction","translationIssue","thumb-down"],["Mauvais exemple/Erreur de code","samplesCodeIssue","thumb-down"],["Autre","otherDown","thumb-down"]],["Dernière mise à jour le 2023/12/08 (UTC)."],[],[],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)"]]