diff --git a/src/mobile-pentesting/android-app-pentesting/android-task-hijacking.md b/src/mobile-pentesting/android-app-pentesting/android-task-hijacking.md index 64d35ef54..fcf7f4c92 100644 --- a/src/mobile-pentesting/android-app-pentesting/android-task-hijacking.md +++ b/src/mobile-pentesting/android-app-pentesting/android-task-hijacking.md @@ -8,22 +8,22 @@ W Androidzie, **task** to zasadniczo zestaw aktywności, z którymi użytkownicy Oto szybkie podsumowanie przejść między aktywnościami: -- **Activity 1** zaczyna jako jedyna aktywność w foreground. -- Uruchomienie **Activity 2** przesuwa **Activity 1** do back stack, przynosząc **Activity 2** na foreground. -- Rozpoczęcie **Activity 3** przesuwa **Activity 1** i **Activity 2** dalej w stosie, z **Activity 3** teraz na przodzie. -- Zamknięcie **Activity 3** przywraca **Activity 2** na foreground, pokazując uproszczony mechanizm nawigacji zadań w Androidzie. +- **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](<../../images/image (698).png>) --- -## Task affinity attacks +## Ataki na affinity zadań -`taskAffinity` informuje Android, do którego tasku `Activity` *preferuje* należeć. Gdy dwie aktywności dzielą tę samą afinitet, **Android ma prawo połączyć je w tym samym back-stack, nawet jeśli pochodzą z różnych APK**. +`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 **root** 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ń. +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 afinitet równy 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. +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" @@ -39,8 +39,8 @@ android:launchMode="singleTask" > ``` -2. Złośliwa aplikacja jest uruchamiana raz, aby task (z fałszywą afinitetą) istniał w ostatnich zadaniach. -3. Gdy użytkownik później otworzy prawdziwą aplikację, Android stwierdza, że już istnieje task, którego **root affinity pasuje do pakietu** i po prostu przynosi ten task na foreground. +2. Złośliwa aplikacja jest uruchamiana raz, aby zadanie (z fałszywą affinity) istniało w ostatnich zadaniach. +3. 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. 4. Interfejs użytkownika atakującego jest wyświetlany jako pierwszy. ### Wariant Default–Affinity (bez `singleTask`) – Studium przypadku Caller ID @@ -52,7 +52,7 @@ Wrażliwość zgłoszona w aplikacji **Caller ID (caller.id.phone.number.block)* class HackActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) -moveTaskToBack(true) // utrzymuje task w ostatnich, ale poza zasięgiem wzroku +moveTaskToBack(true) // utrzymaj zadanie w ostatnich, ale poza zasięgiem wzroku } } ``` @@ -67,37 +67,78 @@ android:taskAffinity="com.caller.id.phone.number.block" > ``` -3. Gdy użytkownik zainstaluje i otworzy złośliwą aplikację **raz**, istnieje task, którego afinitet równa się pakietowi ofiary (ale siedzi w tle). -4. Gdy uruchamiana jest prawdziwa aplikacja Caller ID, Android ponownie wykorzystuje ten task i przynosi `HackActivity` na foreground → okno phishingowe/nadużycie uprawnień. +3. 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). +4. 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 tasku domyślnie, co łagodzi ten konkretny wariant. Starsze wersje pozostają narażone. +> 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. --- -## Detection & Exploitation checklist +### StrandHogg 2.0 (CVE-2020-0096) – Przejęcie zadania oparte na refleksji -1. Pobierz `AndroidManifest.xml` z docelowego APK i sprawdź, czy każda `` (lub globalny element ``) zawiera `android:taskAffinity=""` (pusty) **lub** dostosowaną wartość. -2. Jeśli nie, stwórz złośliwą aplikację: -- `android:taskAffinity` = nazwa pakietu ofiary. -- Zapewnij intencję `MAIN/LAUNCHER`, aby użytkownik mógł ją otworzyć raz. -- Opcjonalnie wywołaj `moveTaskToBack(true)`, aby natychmiast się ukryć. -3. Pozwól ofierze otworzyć swoją legalną aplikację → przejęcie. +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. -## Mitigation +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`](https://developer.android.com/reference/android/app/ActivityManager#getRunningTasks(int)) 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 `` (lub globalny element ``) zawiera `android:taskAffinity=""` (puste) **lub** dostosowaną wartość. Narzędzia takie jak: +```bash +# 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 +``` +2. **Przegląd dynamiczny** – Na urządzeniu otwórz docelową aplikację i wylistuj zadania: +```bash +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](https://github.com/WithSecureLabs/drozer)**: +```bash +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 `` (zalecane) **lub** nadać każdej aktywności unikalną, prywatną afinitet. -* Dla wysoce wrażliwych ekranów, połączyć powyższe z `android:launchMode="singleInstance"` lub nowoczesnymi [`setLaunchMode`](https://developer.android.com/reference/android/content/pm/ActivityInfo#launchMode) zabezpieczeniami. -* Zaktualizować `targetSdkVersion` aplikacji i egzekwować **zmiany w zachowaniu Androida 11**, gdzie taski nie są domyślnie dzielone między pakietami. +* Wyraźnie ustawić `android:taskAffinity=""` na poziomie `` (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`](https://developer.android.com/reference/android/content/pm/ActivityInfo#launchMode). +* 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. --- -## References +## 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 12–14 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 - [https://blog.dixitaditya.com/android-task-hijacking/](https://blog.dixitaditya.com/android-task-hijacking/) - [https://blog.takemyhand.xyz/2021/02/android-task-hijacking-with.html](https://blog.takemyhand.xyz/2021/02/android-task-hijacking-with.html) - [Android Manifest Misconfiguration Leading to Task Hijacking in Caller ID app](https://github.com/KMov-g/androidapps/blob/main/caller.id.phone.number.block.md) - [https://medium.com/mobile-app-development-publication/the-risk-of-android-strandhogg-security-issue-and-how-it-can-be-mitigated-80d2ddb4af06](https://medium.com/mobile-app-development-publication/the-risk-of-android-strandhogg-security-issue-and-how-it-can-be-mitigated-80d2ddb4af06) +- [Promon – StrandHogg 2.0 (CVE-2020-0096) technical write-up](https://promon.io/resources/downloads/strandhogg-2-0-new-serious-android-vulnerability) +- [USENIX 2025 – TapTrap: Animation-Driven Tapjacking on Android](https://www.usenix.org/conference/usenixsecurity25/presentation/beer) {{#include ../../banners/hacktricks-training.md}}