Oczekujące intencje

Kategoria OWASP: MASVS-PLATFORM: Platform Interaction

Omówienie

PendingIntent to odwołanie do tokena obsługiwanego przez system. Aplikacja A może przekazać PendingIntent aplikacji B, aby umożliwić jej wykonywanie wstępnie zdefiniowanych działań w imieniu aplikacji A, niezależnie od tego, czy aplikacja A jest nadal aktywna.

Ryzyko: zmienne oczekujące intencje

Intencje oczekujące mogą być zmienne, co oznacza, że wewnętrzna intencja określająca działanie może zostać zaktualizowana przez aplikację B zgodnie z logiką opisaną w dokumentacji fillIn(). Innymi słowy, niewypełnione pola PendingIntent mogą zostać zmodyfikowane przez złośliwą aplikację i umożliwić dostęp do komponentów w aplikacji podatnej na ataki, które w innej sytuacji nie byłyby wyeksportowane.

Wpływ

Wpływ tej podatności na działanie aplikacji zależy od implementacji docelowej niewyeksportowanej funkcji aplikacji.

Środki zaradcze

Ogólne

Aby uniknąć najgroźniejszych luk w zabezpieczeniach, sprawdź, czy działanie, komponent i pakiet są prawidłowo skonfigurowane:

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

Oznacz jako NIEZMIENIANY

Jeśli Twoja aplikacja jest kierowana na Androida 6 (poziom interfejsu API 23) lub nowszego, określ zmienność. Można to zrobić na przykład za pomocą FLAG_IMMUTABLE, aby zapobiec wypełnianiu pustych pól przez złośliwą aplikację:

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

W Androidzie 11 (poziom API 30) i nowszych należy określić, które pola mają być zmienne. Pozwala to ograniczyć przypadkowe luki w zabezpieczeniach tego typu.

Materiały


Ryzyko: odtwarzanie oczekujących intencji

Zawieszoną prośbę można odtworzyć, chyba że ustawiona jest flaga FLAG_ONE_SHOT. Aby uniknąć ataków metodą powtórzenia (czynności, które nie powinny być powtarzalne), ważne jest używanie parametru FLAG_ONE_SHOT.

Wpływ

Wpływ tej luki w zabezpieczeniach zależy od implementacji strony odbierającej intencji. Złośliwa aplikacja wykorzystująca PendingIntent, który został utworzony bez ustawienia flagi FLAG_ONE_SHOT, może przechwycić i ponownie użyć intencji, aby powtórzyć działania, które powinny być wykonywane tylko raz.

Środki zaradcze

Zawieszone intencje, które nie mają być wywoływane wielokrotnie, powinny używać flagi FLAG_ONE_SHOT, aby uniknąć ataków polegających na odtwarzaniu.

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

Materiały


Materiały