Android Task Hijacking

Reading time: 7 minutes

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 지원하기

Task, Back Stack and Foreground Activities

안드로이드에서 task는 사용자가 특정 작업을 완료하기 위해 상호작용하는 활동의 집합으로, back stack 내에 조직됩니다. 이 스택은 활동이 열린 순서에 따라 정렬되며, 가장 최근의 활동이 foreground activity로 화면 상단에 표시됩니다. 언제든지 이 활동만 화면에 보이므로 foreground task의 일부가 됩니다.

활동 전환에 대한 간단한 요약은 다음과 같습니다:

  • Activity 1은 foreground에서 유일한 활동으로 시작됩니다.
  • Activity 2를 시작하면 Activity 1이 back stack으로 밀려나고, Activity 2가 foreground로 올라옵니다.
  • Activity 3을 시작하면 Activity 1Activity 2가 스택에서 더 뒤로 밀리고, Activity 3이 앞에 위치합니다.
  • Activity 3을 닫으면 Activity 2가 다시 foreground로 돌아와 안드로이드의 간소화된 작업 탐색 메커니즘을 보여줍니다.

https://developer.android.com/images/fundamentals/diagram_backstack.png


Task affinity attacks

taskAffinity는 안드로이드에 Activity선호하는 작업을 알려줍니다. 두 활동이 동일한 affinity를 공유할 경우 안드로이드는 서로 다른 APK에서 온 경우에도 동일한 back-stack 내에서 이를 병합할 수 있습니다.

공격자가 그 스택의 root에 악성 활동을 배치할 수 있다면, 피해자가 합법적인 애플리케이션을 열 때마다 악성 UI가 사용자가 가장 먼저 보는 것이 됩니다 – 피싱이나 악용 권한 요청에 완벽합니다.

공격 표면은 많은 개발자들이 생각하는 것보다 넓습니다. 왜냐하면 모든 활동은 자동으로 애플리케이션 패키지 이름과 동일한 affinity를 상속받기 때문입니다 (개발자가 android:taskAffinity=""를 설정하지 않는 한). 따라서 아무것도 하지 않는 것만으로도 안드로이드 11 이전 버전에서 작업 탈취에 노출됩니다.

Classic "singleTask / StrandHogg" scenario

  1. 공격자는 다음과 같이 활동을 선언합니다:
xml
<activity android:name=".EvilActivity"
android:exported="true"
android:taskAffinity="com.victim.package"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
  1. 악성 앱이 한 번 시작되어 (스푸핑된 affinity를 가진) 작업이 최근 작업에 존재하게 됩니다.
  2. 사용자가 나중에 실제 애플리케이션을 열면 안드로이드는 이미 root affinity가 패키지와 일치하는 작업이 있음을 찾아 그 작업을 foreground로 가져옵니다.
  3. 공격자의 UI가 먼저 표시됩니다.

Default–Affinity (no singleTask) variant – Caller ID case study

Caller ID (caller.id.phone.number.block) 애플리케이션에서 보고된 취약점은 공격이 기본 standard 실행 모드에서도 작동함을 보여줍니다:

  1. 공격자 애플리케이션이 가짜 루트 활동을 생성하고 즉시 자신을 숨깁니다:
kotlin
class HackActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
moveTaskToBack(true)   // 작업을 최근 목록에 유지하되 시야에서 벗어남
}
}
  1. 매니페스트는 피해자 패키지를 taskAffinity에 복사하기만 하면 됩니다:
xml
<activity android:name=".HackActivity"
android:exported="true"
android:taskAffinity="com.caller.id.phone.number.block" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
  1. 사용자가 악성 앱을 한 번 설치하고 열면 피해자 패키지와 동일한 affinity를 가진 작업이 존재하게 됩니다 (하지만 백그라운드에 위치).
  2. 실제 Caller ID 애플리케이션이 실행되면 안드로이드는 그 작업을 재사용하고 HackActivity를 foreground로 가져옵니다 → 피싱 창/권한 남용.

NOTE: **Android 11 (API 30)**부터 시스템은 기본적으로 동일한 UID에 속하지 않는 두 패키지를 동일한 작업에 배치하지 않으므로 이 특정 변형을 완화합니다. 이전 버전은 여전히 취약합니다.


StrandHogg 2.0 (CVE-2020-0096) – Reflection-based task hijack

구글의 2020년 5월 보안 공지는 StrandHogg 2.0이라는 더 고급 변형을 수정했습니다. 이 익스플로잇은 전혀 taskAffinity에 의존하지 않으며; 대신 reflection을 사용하여 공격자의 활동을 모든 실행 중인 작업의 맨 위에 동적으로 삽입하여 안드로이드 11에서 도입된 “shared-UID” 제한을 완전히 우회합니다.

주요 사항:

  • 제로 권한 악성 앱은 한 번 열리면 실행 중인 작업을 반복하고 숨겨진 API를 호출하여 자신의 활동을 어떤 작업으로든 재부모화할 수 있습니다.
  • 활동이 런타임 후에 삽입되기 때문에 launchMode나 정적 매니페스트 분석으로는 공격을 사전에 감지할 수 없습니다.
  • Android 8.0/8.1/9에 체크를 백포트하여 패치되었습니다 (2020년 5월 SPL). Android 10 이상은 영향을 받지 않습니다.

패치되지 않은 장치에서의 탐지는 adb shell dumpsys activity activities를 사용하여 수행할 수 있으며, 작업의 affinity와 패키지 이름이 다른 의심스러운 활동을 감시합니다.

구형 장치에 대한 완화는 고전적인 작업 탈취와 동일하며 + 런타임 검증이 필요합니다 (예: ActivityManager#getRunningTasks를 호출하고 자신의 패키지 이름을 검증).


Detection & Exploitation checklist

  1. Static review – 대상 APK에서 AndroidManifest.xml를 가져와 각 <activity> (또는 전역 <application> 요소)가 android:taskAffinity="" (비어 있음) 또는 사용자 정의 값을 포함하는지 확인합니다. 도구 예시:
bash
# apkanalyzer (Android SDK) 사용
apkanalyzer manifest print app.apk | grep -i taskaffinity

# AXMLPrinter2 사용
java -jar AXMLPrinter2.jar AndroidManifest.xml | grep taskAffinity
  1. Dynamic review – 장치에서 대상 앱을 열고 작업 목록을 나열합니다:
bash
adb shell dumpsys activity activities | grep -A3 "TASK" | grep -E "Root|affinity"

루트 affinity가 피해자 패키지와 같지만 최상위 활동이 다른 패키지에 속하는 작업은 경고 신호입니다. 3. 위에서 설명한 대로 악성 앱을 제작하거나 **Drozer**를 사용합니다:

bash
drozer console connect
run app.activity.start --component com.victim/.MainActivity --action android.intent.action.MAIN
run app.activity.info com.victim

Mitigation

개발자는 다음을 수행해야 합니다:

  • <application> 수준에서 android:taskAffinity=""를 명시적으로 설정하는 것이 좋습니다 또는 각 활동에 고유하고 개인적인 affinity를 부여합니다.
  • 매우 민감한 화면의 경우 위의 방법과 android:launchMode="singleInstance" 또는 현대적인 setLaunchMode 보호를 결합합니다.
  • 앱의 targetSdkVersion을 업그레이드하고 기본적으로 패키지 간에 작업이 공유되지 않는 Android 11의 동작 변경 사항을 시행합니다.
  • Android 12 (API 31) 이상을 목표로 하여 필수 android:exported 속성이 개발자가 외부에서 접근 가능한 모든 구성 요소를 감사하도록 강제합니다.
  • 런타임 자기 방어를 고려합니다: 주기적으로 ActivityTaskManager를 쿼리하여 최상위 활동의 패키지가 자신의 것과 일치하는지 확인합니다.

작업 탈취는 종종 tapjacking (오버레이 기반 UI 속임수)와 결합되거나 대체됩니다. 2025년 TapTrap 연구는 완전히 투명한 애니메이션 기반 활동이 안드로이드 12–14에서 도입된 오버레이 터치 제한을 우회하고 여전히 사용자가 위험한 권한을 부여하도록 속일 수 있음을 보여주었습니다. TapTrap은 엄밀히 말해 task 탈취는 아니지만, 최종 목표(피싱 클릭)는 동일하므로 현대적인 평가에서는 두 공격 표면을 모두 확인해야 합니다.


References

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 지원하기