Intents pendentes

Categoria do OWASP: MASVS-PLATFORM - Interação com plataformas

Visão geral

Uma PendingIntent é uma referência a um token mantido pelo sistema. O aplicativo A pode transmitir uma PendingIntent para o app B, permitindo que ela execute ações predefinidas em nome do aplicativo original, independente de ele continuar ativo ou não.

Risco: intents pendentes mutáveis

Uma PendingIntent pode ser mutável, ou seja, a intent interna que especifica a ação pode ser atualizada pelo app B seguindo a lógica descrita na documentação de fillIn(). Em outras palavras, os campos não preenchidos de uma PendingIntent podem ser modificados por um app malicioso e permitir o acesso a componentes não exportados do aplicativo vulnerável.

Impacto

O impacto dessa vulnerabilidade varia de acordo com a implementação da funcionalidade não exportada do app.

Mitigações

Geral

Verifique se a ação, o componente e o pacote estão definidos para evitar as piores vulnerabilidades:

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);

Flag IMMUTABLE

Caso o app seja destinado ao Android 6 (nível 23 da API) ou versões mais recentes, especifique a mutabilidade. Isso pode ser feito, por exemplo, usando FLAG_IMMUTABLE para impedir que campos em branco sejam preenchidos por um aplicativo malicioso:

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);

No Android 11 (nível 30 da API) e versões mais recentes, é necessário especificar quais campos serão mutáveis. Isso reduz as vulnerabilidades acidentais desse tipo.

Recursos


Risco: repetir intents pendentes

Uma PendingIntent pode ser repetida, a menos que a flag FLAG_ONE_SHOT seja definida. É importante usar FLAG_ONE_SHOT para evitar ataques repetidos, ou seja, realizar ações que não deveriam ser repetidas.

Impacto

O impacto dessa vulnerabilidade varia de acordo com a implementação usada pelo destino final da intent. Um app malicioso que explora uma PendingIntent criada sem definir a flag FLAG_ONE_SHOT pode capturar e reutilizar a intent para repetir ações que só deveriam poder ser feitas uma vez.

Mitigações

As intents pendentes que não devem ser disparadas várias vezes precisam usar a flag FLAG_ONE_SHOT para evitar ataques.

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);

Recursos


Recursos