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
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
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
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
Lesson #2: Controlled Exports Should Require Signatures
In the Kies incident, Samsung published a
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:
In both apps, have the same
<permission>element, with the same permission name, plus
<receiver>element, add the
android:permissionattribute, naming this shared permission
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
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
action. Had this been named
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
/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
Intentaction something like
com.intent.action.KIES_APP_STARTunless you actually own the
intent.comdomain name. Based on the
whoisdata 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