Intents en attente

Catégorie OWASP : MASVS-PLATFORM : interaction avec la plate-forme

Présentation

Un PendingIntent (intent en attente) est une référence à un jeton géré par le système. L'application A peut transmettre un PendingIntent à l'application B afin de lui permettre d'exécuter des actions prédéfinies en son nom, que l'application A soit toujours active ou non.

Risque : intents en attente modifiables

Un PendingIntent peut être modifiable. Cela signifie que l'intent interne qui spécifie l'action peut être mis à jour par l'application B selon la logique décrite dans fillIn(). En d'autres termes, les champs non renseignés d'un PendingIntent peuvent être modifiés par une application malveillante et permettent d'accéder à des composants autrement non exportés de l'application vulnérable.

Impact

Les conséquences de cette faille varient en fonction de l'implémentation de la fonctionnalité non exportée ciblée de l'application.

Stratégies d'atténuation

Général

Assurez-vous que l'action, le composant et le package sont définis pour éviter les pires failles :

Kotlin

val intent = Intent(intentAction)

// Or other component setting APIs e.g. setComponent, setClass
intent.setClassName(packageName, className)

PendingIntent pendingIntent =
    PendingIntent.getActivity(
        context,
        /* requestCode = */ 0,
        intent, /* flags = */ PendingIntent.FLAG_IMMUTABLE
    )

Java

Intent intent = new Intent(intentAction);

// Or other component setting APIs e.g. setComponent, setClass
intent.setClassName(packageName, className);

PendingIntent pendingIntent =
        PendingIntent.getActivity(
            getContext(),
            /* requestCode= */ 0,
            intent, /* flags= */ 0);

Indicateur IMMUTABLE

Si votre application cible Android 6 (niveau d'API 23) ou une version ultérieure, spécifiez la modification. Par exemple, vous pouvez utiliser FLAG_IMMUTABLE pour éviter que des champs non remplis ne soient remplis par une application malveillante :

Kotlin

val pendingIntent =
    PendingIntent.getActivity(
        context,
        /* requestCode = */ 0,
        Intent(intentAction),
        PendingIntent.FLAG_IMMUTABLE)

Java

PendingIntent pendingIntent =
        PendingIntent.getActivity(
            getContext(),
            /* requestCode= */ 0,
            new Intent(intentAction),
            PendingIntent.FLAG_IMMUTABLE);

Sur Android 11 (niveau d'API 30) ou version ultérieure, vous devez spécifier les champs à rendre modifiables, ce qui réduit les risques de failles accidentelles de ce type.

Ressources


Risque : relancer des intents en attente

Un PendingIntent peut être relancé, sauf si l'indicateurFLAG_ONE_SHOT est défini. Il est important d'utiliser FLAG_ONE_SHOT pour éviter les attaques par rejeu (exécution d'actions qui ne doivent pas être répétées).

Impact

Les conséquences de cette faille varient en fonction de l'implémentation de la réception de l'intent. Une application malveillante qui exploite un PendingIntent créé sans définir l'indicateur FLAG_ONE_SHOT peut capturer et réutiliser l'intent pour répéter des actions qui ne doivent pas être effectuées plus d'une fois.

Stratégies d'atténuation

Les intents en attente qui ne sont pas destinés à être déclenchés plusieurs fois doivent utiliser l'indicateur FLAG_ONE_SHOT pour éviter les attaques par rejeu.

Kotlin

val pendingIntent =
      PendingIntent.getActivity(
          context,
          /* requestCode = */ 0,
          Intent(intentAction),
          PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_ONE_SHOT)

Java

PendingIntent pendingIntent =
        PendingIntent.getActivity(
            getContext(),
            /* requestCode= */ 0,
            new Intent(intentAction),
            PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);

Ressources


Ressources