Sender of Pending Intents
Stay organized with collections
Save and categorize content based on your preferences.
OWASP category: MASVS-CODE: Code Quality
Overview
Using PendingIntent.getCreator*()
or PendingIntent.getTarget*()
to determine whether to trust a PendingIntent's sender creates an
exploitation risk.
PendingIntent.getCreator*()
or
PendingIntent.getTarget*()
returns the PendingIntent's
creator, which does not always match its sender. The creator may be trusted, but
the sender should never be trusted, as the sender might be a malicious app
that acquired another app's PendingIntent using a variety of mechanisms, for
example:
An example of a legitimate use of PendingIntent.getCreator*()
or PendingIntent.getTarget*()
would be to show
the icon of the app that will be started by the PendingIntent.
Impact
Trusting a PendingIntent's sender because you queried (and trust) the creator
can lead to vulnerabilities. If an app trusts the PendingIntent's sender based
on its creator, and then shares its authentication or authorization logic, then
whenever the PendingIntent's sender is a malicious app, this would lead to an
authentication bypass or potentially even remote code execution based on
invalidated, untrusted input, depending on the implementation of the vulnerable
application's code.
Mitigations
Distinguish between sender and creator
Any type of authentication or authorization logic performed when receiving a
PendingIntent must not be based on assumptions regarding the PendingIntent's
creator identified using either PendingIntent.getCreator*()
or PendingIntent.getTarget*()
.
Use alternative ways to validate callers
If you need to authenticate the caller, instead of using PendingIntent, you
should use a Service or ContentProvider – both allow fetching the caller UID
with Binder.getCallingUid() when you are in the context of dispatching an
incoming IPC. The UID can be queried later by using
PackageManager.getPackagesForUid().
Another approach, available from API level 34, would be to use
BroadcastReceiver.getSentFromUid() or
BroadcastReceiver.getSentFromPackage() if the sender opted in to sharing
identity during broadcast using BroadcastOptions.isShareIdentityEnabled().
You should always check if the calling package has the expected signature, as
sideloaded packages can have package names overlapping with ones from the Play
Store.
Resources
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2024-09-24 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2024-09-24 UTC."],[],[],null,["# Sender of Pending Intents\n\n\u003cbr /\u003e\n\n**OWASP category:** [MASVS-CODE: Code Quality](https://mas.owasp.org/MASVS/10-MASVS-CODE)\n\nOverview\n--------\n\nUsing [`PendingIntent.getCreator*()`](/reference/android/app/PendingIntent#public-methods_1) or [`PendingIntent.getTarget*()`](/reference/android/app/PendingIntent#public-methods_1) to determine whether to trust a PendingIntent's sender creates an\nexploitation risk.\n\n[`PendingIntent.getCreator*()`](/reference/android/app/PendingIntent#public-methods_1) or\n[`PendingIntent.getTarget*()`](/reference/android/app/PendingIntent#public-methods_1) returns the PendingIntent's\ncreator, which does not always match its sender. The creator may be trusted, but\nthe sender should **never** be trusted, as the sender might be a malicious app\nthat acquired another app's PendingIntent using a variety of mechanisms, for\nexample:\n\n- from [`NotificationListenerService`](/reference/android/service/notification/NotificationListenerService)\n- legitimate use cases that are part of the vulnerable app.\n\nAn example of a legitimate use of [`PendingIntent.getCreator*()`](/reference/android/app/PendingIntent#public-methods_1) or [`PendingIntent.getTarget*()`](/reference/android/app/PendingIntent#public-methods_1) would be to show\nthe icon of the app that will be started by the PendingIntent.\n\nImpact\n------\n\nTrusting a PendingIntent's sender because you queried (and trust) the creator\ncan lead to vulnerabilities. If an app trusts the PendingIntent's sender based\non its creator, and then shares its authentication or authorization logic, then\nwhenever the PendingIntent's sender is a malicious app, this would lead to an\nauthentication bypass or potentially even remote code execution based on\ninvalidated, untrusted input, depending on the implementation of the vulnerable\napplication's code.\n\nMitigations\n-----------\n\n### Distinguish between sender and creator\n\nAny type of authentication or authorization logic performed when receiving a\nPendingIntent must not be based on assumptions regarding the PendingIntent's\ncreator identified using either [`PendingIntent.getCreator*()`](/reference/android/app/PendingIntent#public-methods_1)\nor [`PendingIntent.getTarget*()`](/reference/android/app/PendingIntent#public-methods_1).\n\n### Use alternative ways to validate callers\n\nIf you need to authenticate the caller, instead of using PendingIntent, you\nshould use a Service or ContentProvider -- both allow fetching the caller UID\nwith [Binder.getCallingUid()](/reference/android/os/Binder#getCallingUid()) when you are in the context of dispatching an\nincoming IPC. The UID can be queried later by using\n[PackageManager.getPackagesForUid()](/reference/android/content/pm/PackageManager#getPackagesForUid(int)).\n\nAnother approach, available from API level 34, would be to use\n[BroadcastReceiver.getSentFromUid()](/reference/android/content/BroadcastReceiver#getSentFromUid()) or\n[BroadcastReceiver.getSentFromPackage()](/reference/android/content/BroadcastReceiver#getSentFromPackage()) if the sender opted in to sharing\nidentity during broadcast using [BroadcastOptions.isShareIdentityEnabled()](/reference/android/app/BroadcastOptions#isShareIdentityEnabled()).\n\nYou should always check if the calling package has the expected signature, as\nsideloaded packages can have package names overlapping with ones from the Play\nStore.\n\nResources\n---------\n\n- [Pending Intent](/reference/android/app/PendingIntent)"]]