LWN.net Logo

Subverting Android package verification

By Jake Edge
July 10, 2013

A bug in Android that Google has known about since February is finally coming to light. It affects the integrity of Android packages, allowing an attacker to create a malicious version of an app that still passes the cryptographic signature check. While it doesn't affect any packages in Google's Play store, it certainly could have affected packages that came from elsewhere—"sideloaded" apps. In fact, since the flaw goes back to Android 1.6 ("Donut") and hasn't been fixed for the vast majority of Android firmware versions, it still affects hundreds of millions of devices.

The actual bug is fairly trivial; a four-line patch is enough to fix it. The problem stems from the fact that the Android ZIP file decoder will allow archives to contain more than one file with the same name. That might not be a big deal, except that there is an inconsistency on which of the two identically named files in the archive is used. It turns out that the Android package verification code uses the last file in the archive, while the app uses the first.

That situation means that an attacker can take an existing, cryptographically signed .apk file (in Android's application package file format—essentially just a ZIP file with defined contents) and massage it into one that will run malicious code, while still passing the signature checks. By placing a malicious file with the same name as a signed file in the archive before the existing files, an attacker gets their fondest wish: an app that passes the security checks but compromises the device.

From a device's perspective, the compromised package looks for all the world like a valid app signed by the app vendor—but it isn't. It contains code that comes from elsewhere but will be run by the device when the app is loaded. So the user gets an app that is rather different than what they expect based on the signature. Bouncing Cows has now become a bouncing Trojan horse.

The problem was discovered by Bluebox Security and reported to Google in February. It was first "announced" in a tweet in March that just referred to the Android bug number (8219321). More information about the flaw came in an early July blog post by Bluebox CTO Jeff Forristal. He called it a "master key" vulnerability, which may have been meant to misdirect others from discovering the flaw. But he also evidently wanted to increase the anticipation for his Black Hat USA talk in August.

It would seem that there was enough information in that post and elsewhere for the CyanogenMod team to figure out the problem. A patch landed in the CyanogenMod tree on July 7 that disabled the multiple filename "feature". A bit more information appears in the CYAN-1602 bug report. Interestingly, the patch comes from Google and was committed into some internal Google tree on February 18. That may suggest the existence of a back channel between Google and CyanogenMod, which would be a good—if, perhaps, surprising—development.

It doesn't require a very sophisticated program to perform the attack, and a simple proof of concept was posted on July 8. It uses Python's ZIP file library, as most ZIP tools will not allow duplicate file names. A more sophisticated, Java-based tool is also available.

The biggest danger is from sideloaded system apps, which have more privileges than regular Android apps. System apps can effectively take over the phone completely to use any of its services or devices as well as to access any installed app and its data. Depending on the phone, however, the system apps may be stored in a read-only part of the system, so it would require a full Android update to change. But there is plenty of damage that a regular app can do, depending on the permissions required when it was installed. Attackers would seem likely to choose to compromise apps with numerous permissions when (ab)using this vulnerability.

In some sense, though, the vulnerability doesn't give the apps any more privileges than they already have. A malicious app (either system or regular) could already perform any of the actions that a compromised app could perform. The difference is that apps in the Play store, or those installed by phone vendors, are not expected to join botnets, send contact information to remote sites, activate the microphone or GPS without user approval, or any other "tricks" that an attacker might want to do.

By giving permission to apps (either explicitly when installing them or implicitly by buying a phone with system apps installed), the user is allowing various types of activities. Apps that violate the expectations will presumably find themselves blocked or removed from the Play store, while misbehaving system apps will, at least, negatively impact the phone vendor or carrier's reputation. Sideloading apps, especially system apps, comes with some inherent risk that may largely not be present when getting them through "normal" channels.

In an interview at the CIO web site, Forristal said that Google blocks Play store apps with duplicate filenames, and Google indicated that none had been found when that blocking began. So the problem exists only for those users who sideload apps from other sites. That may be a minority of Android users, but it still seems like the kind of bug that should have been fixed long ago.

As the CyanogenMod patch indicates, however, Google did fix this in its trees shortly after the report. So far, though, only the Galaxy S4 has been reported to have been updated. The Android Open Source Project (AOSP) code has not been updated with a fix, yet, either. It's a little puzzling why a trivial fix, seemingly with few, if any, downsides, has not seen more proliferation through the Android ecosystem.

In light of Google's disclosure policy, it would seem that the company should have been more forthcoming about this bug. Given that Bluebox is trying to make a splash with the vulnerability at Black Hat, perhaps there was a request—or requirement—to withhold the details, or even existence, of the flaw until after the presentation. If so, it is a sad statement about the state of security vulnerability research and disclosure today.

Cryptographic signing is specifically targeted at preventing precisely this kind of attack, of course. This vulnerability serves as a reminder that it isn't just the cryptographic code that needs vetting, but that all of the steps in the signing and packaging process are important pieces of the puzzle too. In this case, an obscure bug in decoding a decades-old format led to a complete circumvention of the security meant to be provided by the signatures—it makes one wonder what other weird little corner cases lurk out there waiting to be discovered, or exploited.


(Log in to post comments)

Subverting Android package verification

Posted Jul 11, 2013 6:15 UTC (Thu) by kleptog (subscriber, #1183) [Link]

ISTM that the real problem is that what is being signed is not the ZIP but some derivation thereof. This is probably because they want to store the signature in the ZIP file as well. Hence anything lost is the translation of the ZIP to whatever is not really signed. I imagine this would cover timestamps, permissions and possibly ZIP file comments?

Arguably all these things are not security issues but it is an area where mistakes could be made... Detached signatures solve this but they are annoying. Is there a better way to deal with this?

Subverting Android package verification

Posted Jul 11, 2013 16:04 UTC (Thu) by epa (subscriber, #39769) [Link]

Put your app in a zip file (perhaps uncompressed). Then sign it and include the signature and the zip file in another zip file.

Subverting Android package verification

Posted Jul 11, 2013 16:29 UTC (Thu) by cesarb (subscriber, #6266) [Link]

> the real problem is that what is being signed is not the ZIP but some derivation thereof.

That is not the problem.

The problem is that what is being used is not what is signed.

What is being signed is parts of the ZIP file. What is being used is the whole original ZIP file, complete with any unknown junk which it might have.

One way to avoid this class of mistakes would be to:

1. Extract the signed parts, the manifest (which has the signatures), and known metadata (file names, dates, etc).
2. Discard the original ZIP file.
3. Check the signatures.
4. Recreate and align the ZIP file.

Since AFAIK the original ZIP file has also been created via Java, the end result should be identical. Even if not identical, it should only have irrelevant differences (for instance, if the creator of the original ZIP file forgot to run zipalign).

Subverting Android package verification

Posted Jul 11, 2013 8:49 UTC (Thu) by gebi (subscriber, #59940) [Link]

Would be interesting to know if there are further differences in zip verification vs. extract code. Eg. where is the filename taken from (archive header, vs. local file header), how are deleted files handled (is a deleted file possible ignored by the verification but extracted later on, because the archive header is not even read?)

That's imho a big point on why someone should not step down into zip for security reasons and just make a signature over the whole zip file.

Subverting Android package verification

Posted Jul 11, 2013 9:03 UTC (Thu) by johill (subscriber, #25196) [Link]

Making the signature over the entire zip file means they can't store the signature in it, due to the zip format.

Now, if they'd used tar, they could probably sign it and append a signature record to the tar file, and then compress the result. But ...

Stop wondering...

Posted Jul 15, 2013 13:59 UTC (Mon) by ortalo (subscriber, #4654) [Link]

There is nothing to wonder about. Until users give more value to their security, they will keep on pushing the natural selection process to favor unsecure devices (through unaware developers and unwilling manufacturers).

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds