Learning From the Kies Incident

As some of you may already be aware, a couple of exploits were uncovered (then fixed by Samsung) that would allow apps with zero permissions to download and install apps without user confirmation on the Galaxy S3.

Most apps do not have to worry about leaking the INSTALL_PACKAGES capability, simply because most apps do not have that permission in the first place. However, there are some basic app security lessons that can be learned by what befell Samsung in this case.

Lesson #1: Beware the Intent Filter

There is little question that Android’s Intent system, for allowing loose coupling of applications, is drop-dead sexy (in programming terms, that is). And there are some Android developers that advocate that all integration, even within an app, should be done via public Intents and filters. I couldn’t disagree more, and the Kies incident is one example why.

Every time you publish an <intent-filter>, or otherwise export a component (e.g., write a ContentProvider and fail to lock it down), you are exposing an API. Just because the API comes in the form of Intent messages instead of some sort of function calls does not make it any less of an API. And every time you expose an API you need to think about whether you are adequately securing that API.

Hence, I only recommend exporting components and publishing filters for cases where you explicitly want third party code to access your components. For internal purposes, do not use <intent-filter>, and use explicit, component-based Intents instead. Note that you can still put an action string and stuff on an explicit Intent, so it is not like you are going to lose some of your “payload” options for delivering data with the Intent.

Lesson #2: Controlled Exports Should Require Signatures

In the Kies incident, Samsung published a BroadcastReceiver that supported a range of Intent actions unique to Samsung. Ideally, those would not exist.

But, let’s pretend for a moment that they really are needed, that some other app (e.g., another piece of the OS) needs to send those broadcasts for this receiver to pick up.

In that case, you should do what Samsung apparently eventually did: require a signature-level permission.

This is fairly straightforward to implement:

  1. In both apps, have the same <permission> element, with the same permission name, plus android:protectionLevel="signature"

  2. On the <receiver> element, add the android:permission attribute, naming this shared permission

  3. There is no step #3

Instamagically, you lock down these broadcasts. Nobody else can spoof the receiver by sending fake broadcasts, because they will not be signed by the same signing key. And, as a bonus, for SDK apps, the install order does not matter, because they both define the same permission.

Lesson #3: Consider Self-Obfuscation

ProGuard does a yeoman’s job of obfuscating code. However, it will not obfuscate things like action strings on published <intent-filter> elements. Hence, in the Kies incident, it was pretty obvious that this this one BroadcastReceiver could perhaps install apps on demand, because it supported a com.intent.action.KIES_START_RESTORE_APK action. Had this been named com.samsung.action.UNICORNS, or even com.samsung.action.asdw3rioadjsf34e, it would have been less obvious that this component would have been a weak link.

Admittedly, this is “security through obscurity”, which is not really much of a defense. That being said, every speed bump you put between your app and somebody trying to break into it makes it that much less likely that somebody will want to scratch that particular itch.

Lesson #4: Public Stuff is Public

In the Kies incident, the app would, on request, grab everything from /sdcard/restore/ and install it.

This is stupid beyond words. Never blindly assume that stuff on external storage is intrinsically safe, particularly for something as important as finding APK files to install.

Miscellaneous Non-Security Lessons

  • Don’t name an Intent action something like com.intent.action.KIES_APP_START unless you actually own the intent.com domain name. Based on the whois data for that domain, I don’t think Samsung owns it.

  • If the blog post describing this incident is accurate in its portrayal of the source code, Samsung hard-coded /sdcard. Don’t do that. Use the proper Environment methods.