[Android Security] Attacking the Android Package Manager from the past.

image stolen from https://dzone.com/articles/depth-android-package-manager 

Hi folks, here's a quick post about something I see very often in android application code. Something that could have pretty devastating effects if taken too lightly. Something that I believe is known about in some Android development circles but according to some of the things I've seen in apps - it doesn't seem this abuse of the PackageManager is as widely understood as it should be.  So in the following post I'm going to lay out a small trust problem folks seem to miss when dealing with Intents and the PackgeManager on Android.

So here's whats up...

When developing applications for Android you often want to take advantage of other applications and services available on the hosting system. For instance you might want to develop an app that opens Google Maps on a given set of co-ordinates , or perhaps opens a browser on a given page. Of course this is very common, its even common to host applications that forward potentially sensitive information to other applications on a an android system. Often when developers need to establish communication between other potentially un-trusted applications they do so on the basis that they verify certain information about the other apps.

Of course applications have many facets to them that serve as a means to identify them on a system, also certain components of applications can be addressed instead of just an entire package; for instance you might want to use the activity inside an application and not the content provider. In order to locate packages developers use "package" and "component" names and calls to the package manager.  Usually it looks something like this:

Or like this:

But fundamentally they involve stuffing a package name into some of the calls in the PackageManager.java class. The way this works (as far as i know) is as follows. The package manager essentially (from the perspective of this function) serves as a kind of "oracle" or look up service for the contents of the /data/system/packages.xml file, which has entries that look like this:

To give you an example of how this works usually, check out this code from the PackageManagerService.java; this code holds effectively what happens when you interface with the PackageManager via the Android API:

Where mPackages is essentially an array type filled in with the contents of the /data/system/packages.xml file essentially. Among many other details associated to classes, the most crucial include:
  • Package Name of the application. Looks like this usually "com.something.somethingelse".
  • Signature of the package. An application signature is essentially a signature produced by a private key belonging to the developer of the app.
So this must then mean that the package name is essentially tied to the certificate as a means of representation for it (speaking critically one of the things the PackageManager must allow you to do is validate the certificate / package mapping - since this is also what is used to underpin access to the apps resources from an operating system perspective).  Essentially speaking: The package manager enforces an association between a given developer (you identify via the app store); that has been allowed access to run code on your device.

Okay I get how it works, why is this a problem?

So that means that making sure you pay attention to the signatures that correspond to package names could be important in some contexts. Lets say you are sending a literal private key to your GPG app? Or an event to you Anti-Virus app? There is a potentially infinite number of contexts in which Intents and specifically interaction with the Package Manager's app look up functions are very very sensitive and security critical. 

The question obviously is of course how do attackers take advantage of this? Well by beating the legitimate applications to the punch! Install your app using someone else's package name before they can! Of course in a practical exploit this would mean installing an application that claims another package name for instance installing something under com.twitter.android (if that were twitters one) and catching, mangling all the requests to that application or forwarding off the information sent to this package to a malicious party. 

The android system may enforce a strong enough (as far as i know) mapping between the developer identified by the signature and the package name: But it cannot pre-empt or by any great measure prevent apps from using package names on a system before the "legitimate" apps are installed.

If you're pretty experienced at this security stuff; try thinking something like DNS name squatting but with Android Application names instead :) Again, I'm not saying anything new here; just talking about something that to me seems isn't treated crucially enough and leaves many apps open to abuse!

The PackageManager should for all INTENTS and purposes serve as a very humble conduit for what it says in the packages.xml. If you employ the PackageManager against this (lets say in manner that in some context lessens your ability to enact what it says in the packages.xml - the amount of trust you mis place could be pretty devastating! 

For the sake of showing you what a really bad case looks like I present you a good example of where this went wrong. Here the developer relies ONLY on the name of the twitter application to look it up, leaving a would be attacker to fill in whatever certificate and therefore code as a response given they've been squatting effectively:

Here's another example, just to make sure you have more than enough data for your static code scanners ;)

In the above example we can see that the test code seems to aggressively check a number of attributes of the resolved package; except for the very crucial signature! Not going to be a very enlightening unit test when someone starts squatting package names ;)

And if that's not enough; before deciding to write this paragraph off I found another really good example, in this one the code actually grants permissions directly based on an app name. It can be seen here that the app is dishing out URI permissions (potentially for a database or content provider driven intent filter):

Woaw! That's bad; how do I avoid it?

Luckily the fix for this is pretty straight forward; make sure to check your signature where needed. This means if you are sharing information across applications that affects who gets install rights on the device; make sure you have a copy of that applications public key or an effective means to validate the signature.  Here's a good example on how to mitigate this attack by an old friend of mine Scott Alexander :

As you can see in the sample above ample effort is made in pulling out the signature and ensuring it matches with the intended one.