CVE-2024-23712 / Privilege Escalation

CVE-2024-23712: Android Framework Intent Redirection Teardown

How an unvetted nested PendingIntent in Android's ActivityManagerService allowed unprivileged apps to launch internal non-exported activities.

💡 비유를 통한 쉬운 설명 (ELI5)

Imagine an armored courier service that only delivers packages for the president. A trickster hands the courier a package labeled 'Ordinary Letters', but inside the box is a sealed command order that says 'Evacuate the city'. Because the courier blindly opens the inner box and hands it directly to the military, the fake command is executed as if the president ordered it.

핵심 개념 및 서브시스템 용어 해설

Intent
The messaging object used in Android to request an action from another app component (Activity, Service, Receiver).
PendingIntent
A token given to another app granting it the right to execute an operation using the original creator's permissions.
Non-Exported Component
An internal app component marked `android:exported="false"`, meant to be accessible only by the app itself or system services.
Intent Redirection
Tricking a privileged system component into executing a nested Intent against an internal protected target.

단계별 공격 실행 메커니즘

Step 1

1. Malicious App Initial Access

An untrusted app creates a nested Intent pointing to an internal privileged setting activity.

Step 2

2. Packing into System Service Request

The app wraps the nested Intent inside an ordinary notification or account manager request.

Step 3

3. System Dispatches Intent

The privileged system_server extracts the inner Intent and invokes startActivity().

Step 4

4. Security Policy Bypass

Because the sender is system_server (UID 1000), Android allows launching the non-exported activity.

소스 코드 비교: 치명적 취약점 vs 보안 강화 패치

일반 개발자가 쉽게 이해할 수 있는 고수준 소스 코드로 제공 (어셈블리/바이너리 제외).

패치되지 않은 취약점
// VULNERABLE: services/core/java/com/android/server/am/ActivityManagerService.java
public void startServiceWithIntent(Intent wrapperIntent) {
    // ROOT CAUSE:
    // Extracts untrusted nested Intent without validating target component or flags!
    Intent nestedIntent = wrapperIntent.getParcelableExtra("extra_target_intent");
    
    // Dispatches nested intent using SYSTEM_SERVER credentials!
    mContext.startActivity(nestedIntent);
}
보안 강화 패치
// SECURE: ActivityManagerService.java patch
public void startServiceWithIntent(Intent wrapperIntent) {
    Intent nestedIntent = wrapperIntent.getParcelableExtra("extra_target_intent");
    if (nestedIntent == null) return;
    
    // 1. Resolve target component to verify export status
    ResolveInfo resolveInfo = mContext.getPackageManager().resolveActivity(
        nestedIntent, PackageManager.MATCH_DEFAULT_ONLY);
        
    // 2. Reject non-exported components requested by external apps
    if (resolveInfo != null && !resolveInfo.activityInfo.exported) {
        throw new SecurityException("Permission Denial: target activity is not exported");
    }
    
    // 3. Clear dangerous grant flags before dispatch
    nestedIntent.removeFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    mContext.startActivity(nestedIntent);
}

엔지니어링 보안 강화 체크리스트

← 전체 보안 디렉터리 보기 모든 플랫폼 보안 업데이트 →