Chris Vance recently contacted me to assist with a particular Android artifact, and while I was assisting we ran across the file runtime-permissions.xml. As the name suggests, this file contains permissions. Digging further, we found that the file contained app permissions that were different than those found in packages.xml. I did a bit of research on the file, and found while it’s presence is not new, there had been little to nothing written about it. So, we thought a blog post might be in order.
Android app permissions have changed over the years, including the amount of needed permissions and how permissions are granted by a user. That latter point is important, especially when it comes to mobile malware investigations. A user may unknowingly grant permissions to a malicious app masquerading as a legitimate one, which would allow it to surreptitiously access the camera, microphone, send spam SMS messages, or use WiFi/Bluetooth for further propagation. Knowing what app has what permission(s) can help an examiner explain a device’s potentially malicious behavior.
This post will focus on “Dangerous Permissions,” AKA those permissions a user has to explicitly grant/deny an app. These types of permissions are important because they can assist in attributing app usage to a user versus the notorious “It wasn’t me, it must’ve been a virus” reason that tends to pop up occasionally, and help explain any potential malicious behavior occurring on a device.
A Quick Look Back
Prior to Android Marshmallow (6.0) Android apps requested all the permissions they needed at the time of installation. See Figure 1.
A user would either grant/deny all of the permissions at en masse. Granting permissions at installation could get precarious, however. First, if an app had a long list of permissions it needed to operate, a user may get overwhelmed reading a long list of permissions and would just grant everything, not being aware of what exactly they were granting because they didn’t read the entire list. This could be a great way for a malicious app get permissions it needed by flying under the permission radar, so to speak. Second, if a user wanted to revoke permissions they had granted, their only option was to uninstall the app. Google recognized these limitations, and introduced Runtime Permissions. This alleviated the potential for a user granting unneeded permissions to an app, and, as this feature has been enhanced over time, allowed a user to have more granular control over what permissions an app had. For example, a user may be ok with an app having access to their phone’s camera, but may not necessarily want an app to have access to the device location All. The. Time. In Android 11, users can specify when an app can access device location. See Figure 2.
Running With Runtime
Android has four types of permissions: Normal, Signature, signatureOrSystem, and Dangerous (AKA Runtime permissions). If you want to know about the first three permissions, you can read about them here. Dangerous permissions are those that Google believes can potentially cause the most harm to a user/user’s device, and normally asks for permission(s) at the time an app is first run (at “runtime”). A user has to explicity convey to the system whether they grant or deny the permission request. If you are an Android user, you will recognize the dialogue boxes in Figure 3.
The dialogue boxes, such as the ones seen in Figure 3, are typically seen when an app is run for the first time after installation. For some apps, it may be when the app is actually launched for the first time, or it could be after the user logs into their account after having launched the app for the first time; each app is different. Android developer guidance suggests that an app check for permissions each time it is launched, and run accordingly. A user will not see dialogue boxes like those seen in Figure 3 again unless the user tries to use an app feature that requires a permission that was previously denied, in which case the app will ask for that permission again. Even if a dialogue box isn’t presented, a user can adjust permissions in the Android Settings menu to get the desired app functionality if they change their mind later.
The Android Developer website has a listing of Dangerous permissions, which you can find here. There are thirty (30) Dangerous permissions. Some of the more notable are:
Access Location (Background/Coarse/Fine)
Access Body Sensors/Physical Activity
Make Phone Calls (w/out going through Dialer)
Access the Camera
Access Account Information
Read/Write to external media (real or emulated)
Read the Calendar
Read the Call Log
There can be multiple implications here if a malicious app has been granted access to read/send SMS messages, for example. First there can be privacy implications for the user. A user may be sending messages that contains their own sensitive data, or they may receive SMS 2FA messages (tsk tsk). Second, if a user receives, sends, or processes sensitive data such as PHI or PCI, there could be civil implications if this data is exposed, which could affect the user or their organization. In situations like this it is important to remember that a user has to grant Dangerous permissions, in which case the user should be interviewed about their general device usage and whether they remember the origins of the malicious app.
Not every app will ask to get every one of these permissions, however (unless it is Facebook), so, as will be seen, not every app will have an entry for each one of these permissions. Apps are required declare what permissions they need in their APK’s AndroidManifest.xml file, so if an examiner needs to know what permissions an app requested (not necessarily the ones it has), pulling the APK from the device and reading the AndroidManifest.xml file can help. An example of this is seen in Figure 4, which is a snippet of the AndroidManifest.xml file for the Skype APK. The red arrows highlight some of the Dangerous permissions.
If an examiner needs to understand which Dangerous permissions an app actually has on the device, they should examine runtime-permissions.xml (other permissions are documented in packages.xml).
runtime-permissions.xml is not new. I found it in each of my Android images, and where it resides depends on which version of Android is being examined. On devices running Android 10 or below the file resides in /data/system/users/%USERNUMBER%/, and in Android 11 devices, the file resides in /data/misc_de/%USERNUMBER%/apexdata/com.android.permission/. An examiner’s ability to get to this file depends on the ability of the tool(s) being used to get to the respective parts of the file system. The best thing about runtime-permissions.xml is that it contains the status of Dangerous permissions per app in an easy-to-read format, which are, again, set explicitly by a user. These permissions do not appear in packages.xml, which contains only Normal and Signature permissions. Obviously, not every app has a need for Dangerous permissions (again, unless it’s Facebook), so some apps that appear in runtime-permissions.xml will have no data associated with them.
Chris had an interesting find with regards to the file locations. In situations where a phone is upgraded to Android 11, a new runtime-permissions.xml file is created in the Android 11 location (noted above), but the old file from Android 10 (or below) remains; it just isn’t updated any longer and the new file picks up where the old one left off. This could give an examiner an extended event horizon with regards to historical data.
Figure 5 shows a portion of runtime-permissions.xml.
The portion seen here is for Skype (com.skype.raider – blue box). Underneath the package name are the Dangerous permissions the app declared in its AndroidManifest.xml file, along with a Boolean value indicating whether or not the permission was granted (granted=true/false). Generally speaking, if a permission is set by a user to “Deny” or “Ask Every Time” the boolean value will be “false,” and permissions set as “Allow All the Time” and “Allow Only While Using the App” will have a boolean value of true. There are nuances for some of the values, such as those for Location access, so if an examiner needs to understand how Fine, Coarse, and Background location settings interact with each other, I suggest reading the Android developer documentation on permission APIs.
Three things to note here. First, some of the permissions seen in runtime-permissions.xml may be part of a group of Dangerous permissions, so, it will be granted by proxy if a user agreed to granting permission to the group (which is what is presented in the runtime dialogue boxes). Second, permissions in the AndroidManifest.xml file are not parsed into Normal, Signature, and Dangerous categories, so a manual examination of the AndroidManifest.xml file would be needed to determine what Dangerous permissions were declared. Third, knowing that a user has to interact with the app somehow in order to trigger the runtime dialogue boxes (either when the app is first launched or after a user has logged into the account associated with the app) can go towards disproving a user’s claim they did not know about/open/use an app if there are some “true” values present in the app’s runtime-permission.xml entry. This is not definitive, of course; an examiner should cooborrate such findings with other artifacts found on the device.
Again, these permission statuses did not appear in packages.xml.
Beyond the boolean value, there is a field for “flags.” I have not been able to determine what the values represent. I can tell you from testing that they change occasionally when permissions are modified, but there does not seem to be enough consistency to definitively say what information they represent.
As part of this exercise I wanted to see what happened when an app was installed, but not opened, so I installed the Amazon Alex app (com.amazon.dee.app) on my device. Figure 6 shows the Alexa app entry in runtime-permissions.xml prior to first run (blue box).
Because I had not opened the app yet, I had not been given an opportunity via dialogue boxes to grant or deny any of the Dangerous permissions associated with the Alexa app, so all of these permission statuses show as “false.” While not definitive, finding such data could be an indication that an app had not been run by a user. Obviously, an examiner would need to corroborate such data with other artifacts on the phone (e.g. Usage Stats, Digital Wellbeing, etc.) since a user could deny all permissions or change them later, but this could be a good indication to investigate the app further if it happens to be a point of interest during an examination.
The other thing I wanted to check is if runtime-permissions.xml retains data about an app after it has been deleted. Obviously, there are other places an examiner can search in Android to find if an app previously existed on a device, but, as it turns out, runtime-permissions.xml is NOT one of those places. I promptly deleted the Amazon Alexa app, and when I re-checked runtime-permissions.xml the entry for, it was gone. See Figure 7.
I repeated the steps a few more times (download an app, check runtime-permissions.xml, deleted the app, re-check runtime-permissions.xml) and the results were the same each time: the entry for the deleted app was gone.
This is by far my shortest blog post; however, I think knowing about runtime permissions is important. It is beneficial to know what permissions an app has, especially during an investigation into mobile malware. If a malicious app is conducting its bad activity, knowing what permissions the app has can go towards understanding and explaining the malicious behavior coming from the device. It is also important to know that runtime permissions have to be granted or denied by a user, which can go towards attribution, and that Android stores those permissions in a separate location from other permission setting values.
There was a second file in the same directories as runtime-permissions.xml, roles.xml, and you can read about it over at Chris Vance’s blog. Thanks to him for the help with testing. Also, Alexis Brignoni pulled an “Alexis” and has already rolled support for runtime-permissions.xml into ALEAPP. Checkout the screenshot below and go pick it up from Alexis’ GitHub page.