A key part of Anrdoid’s access control policies are permissions. To access certain resources on an Android device, applications need to request and be granted specific permissions. However, beyond those permissions specified by the operations system, an app can define its own customized permissions. Generally, this is done to protect an app’s own functions or data.
Custom permissions like these are usually defined at either the “signature” or “signatureOrSystem” protection levels. These are defined in the Android Open Source Project (AOSP) documentation as:
|signature||A permission that the system grants only if the requesting application is signed with the same certificate as the application that declared the permission. If the certificates match, the system automatically grants the permission without notifying the user or asking for the user’s explicit approval.|
|signatureOrSystem||A permission that the system grants only to applications that are in the Android system image or that are signed with the same certificate as the application that declared the permission. Please avoid using this option, as the signature protection level should be sufficient for most needs and works regardless of exactly where applications are installed. The signatureOrSystem permission is used for certain special situations where multiple vendors have applications built into a system image and need to share specific features explicitly because they are being built together.|
This made Android developers believe that only system applications or applications with the same signature (probably created by the same developer) can access these permissions. Because of this, additional access control may not have been implemented. That is not the case, however.
The Android operating system keeps track of these custom permissions using only their names. Once a permission is defined, other apps cannot modify them. Suppose that a well-known app “A” defined the permission permission-A with a signature protection level in order to protect its own data. However, let’s suppose that before installing A, the user has installed a malicious app B. If B is designed to steal information from the legitimate app A, it would create permission-A before “A” has a chance to create it, and then application “B” can be granted permission-A . Once application “A” installed, “B“ will have the permission to read the protected data of application “A”.
We have found almost 10,000 apps that are at risk to this vulnerability. We are not disclosing which apps are immediately vulnerable, but a quick check we did of vulnerable apps include:
- A popular online store leaks its online browsing history.
- A popular chat app leaks the user’s in-app purchases.
- A popular social network can have fake messages inserted via its app.
Developers should not rely exclusively on the protection levels when their Activities/Receivers/Services/Providers are accessed. Several functions such as getCallingUid and getCallingPackage are provided by the operating system, and can be used to identify any apps requesting the above and implement access control as needed.
We have informed Google’s Android security team about this issue.
With additional analysis from Veo Zhang