12

The current Android Permission System causes the following issue:

App A defines the custom permission of:

com.package.permission.READ_APP_DATA

When app B is installed declaring the custom permission, it is granted.

However, if app A is installed after app B, then the permission is not granted to app B.

Whilst this may not be a common occurrence, due to app B often being a plugin of app A, it of course can occur and does for my application.

With SuperUser applications agreeing to introduce the global custom permission of android.permission.ACCESS_SUPERUSER this may well be a big problem should a user decide to switch SuperUser app.

In order to handle the issue, I intend to use the following code in my application for the custom permission I am about to start declaring:

checkPermissions(this, getCallingActivity().getPackageName()); // get the package name from the sender first

private boolean checkPermissions(Context context, String callingPackage) {

    final List<PackageInfo> apps = context.getPackageManager().getInstalledPackages(PackageManager.GET_PERMISSIONS);

    for (PackageInfo pi : apps) {

        if (pi.packageName.equals(callingPackage)) {

            String[] permissions = pi.requestedPermissions;

            if (permissions != null) {
                for (String permission : permissions) {
                    if (permission.equals("com.package.permission.READ_APP_DATA")) {
                        return true;
                    }
                }
            }
        }
    }
    return false;

As per the title of this question: Is this method 'safe'? Or is there a way/root-hack that an application's manifest could be altered after it is installed and the permission programmatically 'added' to app B?

brandall
  • 6,094
  • 4
  • 49
  • 103
  • 1
    "However, if app A is installed after app B, then the permission is not granted to app B." -- have the same `` element in both apps, particularly if this is a `signature`-level permission. – CommonsWare Oct 18 '13 at 00:11
  • @CommonsWare - Thanks. Could you possibly elaborate though please? I believe this is already what I am doing, but app B permissions are still not detected/granted. I noticed the linked bug report is finally assigned as defect. – brandall Oct 18 '13 at 08:34
  • 1
    "I believe this is already what I am doing" -- your question indicates that only App A has a `` element, and that App B only has a `` element. I am saying to add the `` element to App B as well, so that installation order no longer matters. – CommonsWare Oct 18 '13 at 11:02
  • @CommonsWare - That does indeed work, thank you. Although asking 3rd party developers to declare my custom permissions in this way, feels a little disconcerting; I'm not sure why though... If you have an opinion of the 'safety' of the method detailed above (for apps that don't declare ``) and you want to pop that in an answer, I'll award you the massive 50 bounty! Thanks again. – brandall Oct 19 '13 at 10:25
  • 1
    "Although asking 3rd party developers to declare my custom permissions in this way, feels a little disconcerting" -- as I noted, it's best when you are using a `signature`-level permission, and therefore all affected apps are yours. One of the unfortunate limitations of the permission system is that whoever gets in first gets to define what the permission looks like *to the user* (label and description). There's nothing you can do about that, though. – CommonsWare Oct 19 '13 at 10:29
  • 4
    With regards to your technique above, I have never seen anyone do that. In fact, my original reaction was that it would not work, until I realized that `requestedPermissions` does include non-granted ones. Given that, I don't see any holes, but I think I have the same trepidation that caused you to post this question. :-) If nothing else, make sure you test this all the way back to your `minSdkVersion`, as this feels like one of those areas where Android's behavior could have shifted over the years. – CommonsWare Oct 19 '13 at 10:31
  • @CommonsWare - Thanks for your insight. Appreciated. – brandall Oct 19 '13 at 11:05
  • What about the answer #16, from the link you've provided? I see it was written there one day after you posted this question in SO. – g00dy Oct 22 '13 at 12:27
  • @g00dy - that was me! – brandall Oct 22 '13 at 15:45
  • 2
    Declaring the custom permission in both apps doesn't work any more on Android L (you get an Installation error: INSTALL_FAILED_DUPLICATE_PERMISSION). They seemed to have closed that loophole (see also http://commonsware.com/blog/2014/02/12/vulnerabilities-custom-permissions.html) – Emanuel Moecklin Jul 03 '14 at 13:19

2 Answers2

10

I'm not sure if I'm getting the question right, as I don't know how hacking a permission into the manifest after install connects to the code you posted above. But to answer your last paragraph:

Not in an easy way. The user has to have a mod installed on his device, that can grant arbitrary permissions on the fly while the app is requesting them. IIRC the manifest file itself is parsed just at install time.

So what we used in a mod is altering the method grantPermissionsLPw in class com.android.server.pm.PackageManagerService.

It is used to grant a launcher the permission android.permission.EXPAND_STATUS_BAR, which it didn't declare in its manifest.

I am not sure though, if this would ever be used for your app. But to sum it up: If the user wants to grant an app an arbitray, custom permission: Yes, it is possible.

UPDATE

I can elaborate a bit more, of course. I can see two scenarios happening

1. Static mod

The above mentioned class resides in services.jar. As we know, files like this can be decompiled, altered, and recompiled. Actually, it's a fairly easy edit on this file. I don't know about a way to do this on the phone directly, but I would consider it possible. It's just not that feasible, that widespread solutions are available, as it needs a good amount of processing power. An attacker can't just supply an universal file. These files change from device to device, and also between firmware versions. Either, the attacker would need to supply a huge amount of patched files, or do the patching live, by uploading it to a server, patch it, redownload and install it. This scenario is not very likely if you ask me.

2. dynamic mod

There are more than one frameworks available, that allow altering processes while they opertae. The most popular of them is the Xposed Framework. Basically, it is a patched app_process and a corresponding API that leverages Reflection to alter running processes. Now an attacker can ship his app with this framework, and having root access, install it silently. With root access, he can even enable the module by himself, which normally requires user interaction. Once a module like that is enabled, the attacker can hook into the above mentioned method and alter the requested permissions. He would be doing this by getting the object field, which holds the requested permissions, add the one he requires, THEN run the original method, which adds the originally defined permissions.

Please note that both scenarios require the user to install the malicious app himself. You didn't mention what your app is for, so I can't really help you more with evaluating the risk. All I can say is, that an attacker CAN do things like that.

langerhans
  • 769
  • 7
  • 19
  • Thanks for your answer - Would you be able to elaborate on how the mod works please? It would help me understand the 'risk'. – brandall Oct 23 '13 at 14:07
  • Please see the update above. Corrected the class name too. If you have any more questions, feel free to ask. – langerhans Oct 23 '13 at 16:53
  • 1
    Thanks for the update, it's really helpful and some good linked reading. I'll return to mark your answer as correct and award you the bounty for your efforts. – brandall Oct 23 '13 at 23:33
0

I do see an issue where if App A is installed before App B and the <permission> element isn't declared in App A, the user will never see the permission request. If you do require the use of the <permission> element in App A, though, a similar approach could be used to verify that the label and description shown to the user were accurate.

keyboardr
  • 841
  • 1
  • 8
  • 20