CVE-2023-20918 - Elevation of Privilege in Android's ActivityOptions—How the “Confused Deputy” Bug Can Let Attackers Escalate Privileges Without User Interaction
Android has long been lauded for its security architecture, mainly built on app sandboxing and permissions. However, vulnerabilities can still emerge from subtle bugs that break these guarantees. One of these is CVE-2023-20918, a critical elevation of privilege (EoP) vulnerability involving a “confused deputy” attack in Android’s ActivityOptions class, discovered and patched in 2023.
This long-read breaks down what makes this bug dangerous, how it works under the hood, how attackers might exploit it, and steps you can take as a developer, user, or security enthusiast to defend against it.
What Is CVE-2023-20918?
CVE-2023-20918 is a vulnerability affecting multiple versions of Android, primarily tied to the logic in the getPendingIntentLaunchFlags method in ActivityOptions.java—a core class responsible for managing Intent launch activity in the Android operating system.
User interaction: *None*
- Cause: Confused deputy situation—an attacker abuses a more privileged component to gain higher privileges.
- Android Security Bulletin: May 2023
Android’s ActivityOptions is often used by apps and the system to control how activities (screens) are launched. Mismanagement or leakage of permissions through PendingIntents in this area, especially launch flags, can break core security boundaries.
Explaining the “Confused Deputy” Problem
A “confused deputy” is a classic security bug, where an entity with higher privileges (the “deputy”) is tricked by a lower-privilege entity into performing an action the lower-privilege entity couldn’t normally do.
In Android, this often crosses the boundaries between user apps and system services. If app A can trick a system service into launching something on A’s behalf, but with the system’s privileges, bad things can happen.
The Root Cause
The critical code is in the method getPendingIntentLaunchFlags within the Android framework’s ActivityOptions.java.
The job of this function is to determine and combine the right flags when an activity is launched via a PendingIntent. If there is confusion in how privileges or flags are handled, attackers can exploit the system into performing restricted actions without having the appropriate permissions.
Here’s a simplified version of what the problematic code looked like before the fix
// Vulnerable snippet from ActivityOptions.java:
public int getPendingIntentLaunchFlags() {
int flags = ;
if ((mPendingIntentFlags & FLAG_ACTIVITY_NEW_TASK) != ) {
flags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
// ... Potential missing privilege checks ...
return flags;
}
What’s wrong?
The method doesn’t correctly consider or enforce the context’s permissions when assembling flags. If a malicious app sets certain flags in a PendingIntent and gets a privileged component to use them, it can convince the system to launch activities with escalated privileges—actions the malicious app could never do on its own.
Exploiting CVE-2023-20918
The beauty (and danger) of this vulnerability is how simple it can be to exploit—no user interaction, no extra permissions required.
Malicious app creates a PendingIntent with crafted flags.
2. Malicious app sends this PendingIntent to a system or privileged app or service that happens to use PendingIntents (such as a notification service or broadcast receiver).
3. Privileged component launches the PendingIntent without validating if the launch flags are appropriate for the requester’s privilege.
4. Result: The malicious app piggybacks on the privileged context, effectively escalating its privileges.
Simplified Exploit Code
This is a hypothetical example for educational purposes. Don’t use it for malicious purposes.
// MaliciousApp.java - proof of concept
Intent intent = new Intent(context, SensitiveActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(
context,
,
intent,
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT
);
// Now, send this PendingIntent to a more privileged app/service, e.g., via a broadcast
Intent exploitIntent = new Intent("com.victim.PRIVILEGED_ACTION");
exploitIntent.putExtra("launch_it", pendingIntent);
context.sendBroadcast(exploitIntent);
If the receiving privileged component launches the PendingIntent (common in poorly secured broadcast receivers), the attacker achieves code execution or activity start under elevated privileges—*without user approval*.
Why This Is Dangerous
- No Permissions Needed: The exploit doesn’t require the malicious app to have any dangerous permissions.
No User Interaction: The exploit triggers without user input—no clicks, no dialogs.
- Bypasses Security Barriers: Sensitive activities or actions meant for trusted contexts may be started by untrusted apps.
- Wide impact: Any framework-based code, system app, or vendor app dealing with PendingIntents and ActivityOptions could be vulnerable.
How It Was Fixed
The Android team patched CVE-2023-20918 in the May 2023 Android Security Bulletin. The fix involved stricter checks on launch flags, ensuring that the context’s privileges are always considered, and adding guards to prevent unprivileged PendingIntents from escalating flags.
Example of stronger checks
// After patch, ActivityOptions.java:
public int getPendingIntentLaunchFlags() {
checkCallerPrivilegesOrThrow();
int flags = ;
if ((mPendingIntentFlags & FLAG_ACTIVITY_NEW_TASK) != ) {
flags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
// Additional privilege and context checks
return flags;
}
As a Developer
- Never trust external PendingIntents: Always validate flags, sources, and required permissions before launching anything received from outside your package.
Limit broadcast receiver exposure: Use explicit intents and restrict exports where possible.
- Follow Google’s guidance: See the PendingIntent Security Best Practices.
References & More Reading
- Android Security Bulletin – May 2023
- NVD – CVE-2023-20918 Details
- Android Developer Documentation: PendingIntent
- Confused Deputy Problem Explained - Wikipedia
Conclusion
CVE-2023-20918 is a textbook example of how subtle mistakes in permission handling can break down strong security architectures. By exploiting the confused deputy scenario in core Android ActivityOptions, attackers can quietly escalate privileges—often without any user awareness.
Stay safe: update early, be strict with inter-process communications in your apps, and keep an eye on the always-evolving world of mobile security.
*This write-up was crafted exclusively for your security insight. Please use this knowledge responsibly!*
Timeline
Published on: 07/13/2023 00:15:00 UTC
Last modified on: 07/25/2023 18:02:00 UTC