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
Intent
s 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 Intent
s
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:
-
In both apps, have the same
<permission>
element, with the same permission name, plusandroid:protectionLevel="signature"
-
On the
<receiver>
element, add theandroid:permission
attribute, 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 <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 likecom.intent.action.KIES_APP_START
unless you actually own theintent.com
domain name. Based on thewhois
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 properEnvironment
methods.