Mark L. Murphy's Blog, page 63

September 26, 2013

Android Exported Service MITM Attacks

We are used to a device having multiple activities that can respond to the same <intent-filter>. In that case, by default, the user will see a chooser if we try to start one of those activities.



We are used to a device having multiple BroadcastReceiver components that can respond to the same <intent-filter> (or IntentFilter). In that case, in a regular broadcast, all eligible receivers will receive it.



We are used to it being impossible to have multiple ContentProvider components with the same authority, as the second one fails on install with an INSTALL_FAILED_CONFLICTING_PROVIDER error.



Services, though, follow none of these patterns, and the pattern they do follow raises the possibility of man-in-the-middle (MITM) attacks if you are not careful.



Services that are private to your application (no <intent-filter> or android:exported="false") are safe, as explicit Intents are safe with services, as they stipulate the specific component that you are working with.



Services that are exported but are secured with a signature-level permission are also safe, as only another app signed by the same signing key will be able to work with the service.



But what happens if you want to have a exported service for which a signature-level permission is impossible? For example, what happens if you want to have a service expose an API for third party apps to consume? Those third party apps will be signed by their own signing keys, not yours, and so signature-level permissions will not work.



Without a signature-level permission, there is no automatic validation employed by Android to ensure that the service you are trying to work with is, indeed, the actual service you want to work with, instead of an imposter. Such an imposter might be a totally different service implementation, simply advertising the same <intent-filter> as the real service. Or, the imposter might be a cracked version of the original service app, with additional code injected that makes use of the data flowing between client and service, in addition to doing the normal service behavior.



In the latter case, the cracked version of the app might retain the same package name as your original service implementation. In that case, only one edition of the service can exist on the device, where the first one in “wins”. However, the user will be informed of a problem when they try to install the second such app, and so hopefully they will be able to determine which app is the valid implementation and which is the malware. If, however, they only install the cracked version of the component, the user is in trouble.



In addition, what happens if there are two (or more) services installed on the device that claim to support the same <intent-filter>, but have different package names? You might think that this would fail on install, as happens with providers with duplicate authorities. Alas, it does not. Instead, once again, the first one in “wins”.



So, if we have BadService and GoodService, both responding to the same <intent-filter>, and a client app tries to communicate to GoodService via the explicit Intent matching that <intent-filter>, it might actually be communicating with BadService, simply because BadService was installed first. The user is oblivious to this.



If you want to make sure that you are talking to the right third-party app, by any IPC mechanism, you will need to compare the public keys. The public key that signed an app is part of the APK; only apps signed by the same private key should contain the same public key. Hence, BadService should have a different public key than the expected one, while GoodService would have the expected public key.



You can obtain a binary-encoded edition of the public key from PackageManager. Use getPackageInfo() to retrieve the PackageInfo for an app, given its package name. Pass PackageManager.GET_SIGNATURES as the second parameter to getPackageInfo() to ensure that signature data is retrieved and is part of the PackageInfo structure. Then, the signatures data member of the PackageInfo will contain an array of Signature objects, which, despite their name, are actually binary-encoded versions of the public keys. Calling toByteArray() on a Signature will give you a value that you can compare against a known good binary-encoded version of the public key (e.g., packaged as a raw resource).



This is somewhat tedious, and so over time somebody (possibly me) will need to package this up into something easier for developers to employ. However, you can see some sample code in this area:





An app that will list all installed packages and let you inspect the public key of that package, plus dump a copy of the binary-encoded public key for you to perhaps incorporate into a client app





An app that validates another package given such a binary-encoded public key





A set of three apps demonstrating the above scenario, where we want to ensure that we work with GoodService despite the possibility of a BadService that also advertises support for the same <intent-filter>





(and, yes, a blow-by-blow explanation of this stuff is forthcoming in a future book update)



This code is clunky, and it does not handle apps signed with multiple keys, but it demonstrates some basic defenses that you can employ to avoid rogue service implementations.



Again, this is mostly a concern for IPC where signature-level permissions are not employed for securing that IPC. Non-exported services, or services with signature-level permissions, should not need this sort of work. Conversely, you might consider using this sort of defense for other components as well, such as a ContentProvider, to ensure that you are working with the expected provider, and not a cracked version that does something nefarious with the data being passed back and forth.

 •  0 comments  •  flag
Share on Twitter
Published on September 26, 2013 19:59

September 25, 2013

ROM Modding as Consumer Protection

Yesterday, I blogged about Cyanogen Inc. and their prospects. Those prospects can go up a lot with the work of a few enterprising consumer protection advocates.



There are countless Android devices with security flaws. Some of those flaws have been fixed in newer versions of Android, but device manufacturers and/or carriers have decided not to make those newer versions available for certain devices. Some of those flaws are unique to specific devices, due to engineering failures.



As an example of the latter, Justin Case (nom de plume of an Android security researcher) posted yesterday a disregarded root exploit for the Motorola Defy XT, as shipped by Republic Wireless (a small US MVNO/WiFi firm). Here, by “disregarded”, I mean:




The responsible parties for this have informed me that this issue will not be fixed due to the age of the affected device.




Consumer protection laws exist for many types of products. Imagine that instead of this being a phone with a security flaw, that this was a car with a brake flaw. Once this flaw was publicly discovered, there is no way that the car manufacturer would be able to say “sorry, we are not going to fix it, due to the age of that car model, even though we are still selling it today”.



Consumer protection laws would require the car manufacturer to issue a recall and repair the affected car. There are certainly limits — in the US, car recalls only have to go back 10 years from when the defect was discovered, for example. However, since Republic Wireless sells the Defy XT today, age cannot be a consideration.



Consumer protection laws for smartphones should require one of three possible remedies when a flaw is found that could be used to prevent the use of the device for essential operations (e.g., calling emergency numbers):





Replace the device, for free, with a equal-or-better newer device lacking such flaws





Ship an update to the OS for the device that fixes the flaw, or otherwise supplies tools to device owners to fix the flaw





Allows users to replace the OS on the device with a ROM mod that does not contain that flaw





The third item above, of course, has been part of the argument for allowing ROM mods since the early days; I am saying nothing new here. However, the argument that we hear a lot about ROM mods is “freedom”, and while that is a powerful rationale, it does not always fit the mold of something that existing organizations can latch onto in order to push change. Consumer protection, on the other hand, has been well defined for ~50 years, in the US at least. Finding somebody to fight in Washington (or Sacramento) for consumer protection should be significantly easier than finding somebody to fight for more nebulous, if no less important, aims like “freedom to run what we want”.

 •  0 comments  •  flag
Share on Twitter
Published on September 25, 2013 19:06

Musings on Cyanogen Inc.

It was a bit over a year ago that I blogged “Who Will Become Android’s Red Hat?”.




By this, I mean Android could use a firm that the enterprise and bespoke hardware vendors can turn to for Android firmware, just as Red Hat, particularly in Linux’s early days of adoption, was the go-to firm for enterprise Linux. While other groups had Linux distros, and later firms added an enterprise push (e.g., Canonical), Red Hat was the first serious firm to say “we’re here for business, and will help ordinary consumers and developers some along the way”.




In my list of the possible entrants was:




It could be some new high-flying venture-backed startup, poaching a few engineers from Google and device manufacturers, and perhaps the ROM modding community, to serve as the core team.




Enter Cyanogen Inc..



As has been widely reported, many of the CyanogenMod team members garnered some venture capital backing and formed Cyanogen Inc., with an eye towards building a business around their Android ROM mod. The firm has been in existence since April, and their first major announcement was a partnership with Oppo to have CyanogenMod available for the new Oppo N1.



Will Cyanogen Inc. become Android’s Red Hat? Possibly.



Certainly, they have the capability. Not only do they have the technical chops, but one of their board members was co-founder of 3LM, a firm focused on enterprise security for Android devices. 3LM itself has had a rocky history, being acquried by Motorola Mobility, then apparently mothballed by Google after The Big G acquired Motorola Mobility. Cyanogen Inc. could be another vehicle for 3LM’s technology and intentions, or could simply leverage contacts in this space.



In the short term, the Cyanogen Inc. launch profile may result in some sticking points:





Launching what amounts to a stealth startup around a community-driven project is all but assured to ruffle feathers





License disputes, such as the GPL scuffle over the Focal camera app, will crop up over the next few months as Cyanogen Inc. sets up CyanogenMod to be licensed as it feels it needs





How much these sorts of things impact the launch, and to what extent they are indicative of underlying longer-term issues, remains to be seen. Certainly, plenty of firms have gone on to success with bigger structural issues, though.



From my standpoint, I just don’t know what they plan to do, as they have not announced much beyond the Oppo arrangement and a renewed emphasis on simplifying CyanogenMod installation. IMHO, becoming Android’s Red Hat implies a certain set of business models, and they may or may not elect to embark upon those.



Regardless, I certainly wish Cyanogen Inc. luck. Perhaps Steven J. Vaughan-Nichols was correct when he wrote:




In short, I see CyanogenMod actually helping to unify Android and potentially becoming a major Android player in its own right.


 •  0 comments  •  flag
Share on Twitter
Published on September 25, 2013 00:18

September 17, 2013

More Whirled Tour Updates

If you are contemplating attending AnDevCon, note that the speaker discount codes are now available. Using the last name of a conference speaker as the discount code in checkout will net you $200 off the conference registration fee. This stacks on top of whatever discount you get for early registration (e.g., you will save a total of $600 for registering by this Friday). As noted in an earlier blog post, I have a pair of presentations at AnDevCon this year.



If you have been considering the Samsung Developer Conference, I was mistaken in my earlier blog post about the registration deadline. Registrations are still being accepted, though there are a limited number of seats available. They have also updated their site with more details (yay!) and my photo (ummmm…).



Also, note that both the Samsung Developer Conference and droidcon UK are offering hackathons as adjuncts to their main events, should you be interested in showing off your sleep-deprived coding skills.

 •  0 comments  •  flag
Share on Twitter
Published on September 17, 2013 17:05

September 16, 2013

Whirled Tour Addition: Pushing the UI Envelope

A couple of weeks ago, I blogged about the 2013 CommonsGuy Whirled Tour, listing eight presentations that I am delivering at seven venues on two continents over a bit less than five weeks.



But, why stop there?



On October 22nd, I will be delivering a day-long seminar on “Pushing the UI Envelope” for Skills Matter at their Fleet Street facility in London.



(note to self: avoid all barbers that day, and stay away from the meat pies)



In this seminar, we will:





Dive into advanced areas of the action bar, including action modes, custom action views, dynamic contents, and more





Take a swipe through ViewPager, including advanced techniques like adding and removing pages on the fly





Peek at how to support external displays (HDMI, Miracast, Samsung’s AllShare Cast, MHL, etc.), including how to target separate content to the external display from what you show on the phone or tablet





Slide into the navigation drawer pattern, with a particular emphasis on Google’s DrawerLayout and Google’s design guidance for such drawers





Spend time on rich text formatting and editing, to go beyond plain ol’ text, and without having to break out a WebView





Tie all of that together into implementations of the master/detail pattern, to support a range of screen sizes from a single code base





Note that this last item will be a somewhat enhanced version of the “In the Brain” session that I will be delivering the following evening. Some of the other segments of this workshop will encompass presentations that I am delivering on the US West Coast at Samsung DevCon and AnDevCon, for those of you who will not be able to attend those events.



With three presentations and this full-day workshop, those in the London area the week of 21 October are invited to get tired of listening to me talk. :-)

 •  0 comments  •  flag
Share on Twitter
Published on September 16, 2013 16:22

September 11, 2013

Beware Accidental APIs: Avoid Intents as Extras

Earlier this year, I wrote a blog post warning developers about exposing broadcast receivers to third parties, as this creates an API that third parties might use, for good or ill.



However, the problem of accidental APIs is more general, and sometimes more subtle, than this. Screwing up what you allow third party apps to do can have some serious costs to you or your users.



A couple of weeks ago, Ars Technica wrote a post describing an academic paper that, in turn, documented violations of the “same-origin policy” with mobile apps. Alas, both are a bit terse on the nature of the problem, let alone any solution that does not involve modifying Android itself. In this post, I would like to dive into one of these scenarios a bit more deeply: using Intents as extras.



You are writing an Android app that requires a login.



So, you create a LoginActivity, which has fields for a user ID and a password. You set that up to be the “front door” for your app, by giving that activity the standard MAIN/LAUNCHER <intent-filter> that puts an icon for LoginActivity in the home screen’s launcher. Now, when the user taps on the icon, they have to log in before proceeding. From there, you turn around and call startActivity() to bring up MainActivity, where you show your top-level content.



And life is good.



However, you eventually realize that the user might get into your application by other avenues:





They might click on a Notification that you elect to display





They might click on a link in a Web page to a URL that your application has elected to handle





They might use the recent-tasks list to come back to your app





In any of these cases, it is possible that their old login is now considered stale. Perhaps the process had been terminated, and therefore you do not have any login credentials. Perhaps the process had been around, but it has been a while since they were last in your app, and you want to re-authenticate them.



However, while you want to log them in again, you do not want to break the user intention. If they clicked on a link to go view some specific piece of content, after logging in, they should go to that specific piece of content, not to your top-level content as shown by MainActivity. Likewise, if they use the recent-tasks list and the system wants to return the user somewhere deep in your app (because that’s where they had last been), after logging in, you should take them to that point.



The solution that you might employ here is:





In the activity that is brought up by the Notification / URL / recent-tasks entry / whatever, detect that the user’s login credentials are stale or missing.





In that case, craft an Intent that will take the user back to this same spot. You might be able to get away with just using getIntent() to retrieve the Intent that was used to start up this activity in the first place.





Craft an Intent that leads to the LoginActivity, putting the Intent from the previous step into an Intent extra, then call startActivity() to bring up LoginActivity.





LoginActivity, once the user successfully logs in, looks for that Intent extra. If it exists, it calls startActivity() on that Intent. If it does not exist, just do what you did before, and call startActivity() to bring up MainActivity.





Life seems good. In reality, you have just giving an attacker a means of messing around with your app.



Specifically, LoginActivity is blindly calling startActivity() on the supplied Intent as an extra. In fact, if you went a bit more opaque and elected to wrap that Intent in a PendingIntent, and pass the PendingIntent as an extra, LoginActivity would have no choice but to blindly execute it. You cannot get at the underlying Intent of a PendingIntent to examine it, and therefore LoginActivity would have no means to “sanitize the input”, even if you thought to do that.



You are assuming that the extra is coming from one of your other activities. However, LoginActivity is exported (by means of the MAIN/LAUNCHER <intent-filter>). Hence, any app on the device can call startActivity() on LoginActivity, have you log in, and then have you redirect to the activity of the other app’s choice.



Moreover, you are doing that from within your own process. Hence, even though MainActivity might not be exported, the third-party app could force you to open MainActivity. And the same holds true for any other private (non-exported) activity in your app.



At this point, you still might be wondering what the problem is. After all, displaying your activities is a good thing, right?



Not necessarily.



The researchers who wrote the white paper used this “next-intent” attack to gain control over a user’s Dropbox account:




For the Dropbox app, we exploited a private Activity VideoPlayerActivity, which has an input parameter “EXTRA_METADATA_URL” that specifies a URL from which to fetch the metadata for a video file. In a normal situation, this URL points to a file kept by dropbox.com. However, our next-intent exploit enables a malicious app to set the URL to arbitrary web domain, such as “http://attacker.com”. When the Dropbox app makes a request with that URL, it always assumes the recipient to be dropbox.com and attaches to the request an authentication header, as opposed to applying the conventional origin-based cookie policy. Since right now, EXTRA_METADATA_URL points to “http://attacker.com”, the adversary gets the header and can use it to gain a full access to the user’s Dropbox account.




Similarly, suppose LoginActivity attached the authentication credentials to the “next” Intent (as extras) before calling startActivity(). An attacker could simply have the “next” Intent point to the attacker’s own app, then read those extras and use them for malicious means.



One solution would be to not launch LoginActivity to have the user log in again. Instead, move the authentication behaviors to a LoginFragment, that LoginActivity can use as a regular fragment and that other activities can use as a DialogFragment, blocking access until the user authenticates.



Another solution would be to make LoginActivity not be exported. Have a separate MAIN/LAUNCHER activity (e.g., LauncherActivity). This activity might not do much of anything, other than call startActivity() to bring up LoginActivity. However, since the “next-intent” exploit in this case requires that an attacker be able to directly invoke LoginActivity with a nasty Intent extra, keeping LoginActivity as not-exported will block such access.



In general, if your code is accepting an Intent or a PendingIntent as input (via an Intent extra, via an entry in a Bundle, via an AIDL parameter, etc.), you need to be sure that the only party who can send you that Intent is yourself. If third parties can craft that Intent or PendingIntent, it could be used against you.



The authors of the paper outlined a solution, to be added to Android itself, that would record the “origin” of any Intent objects, and therefore allow you to confirm that a received Intent really did originate with your own app, versus an attacker. This would be a nice improvement to Android, and perhaps we will see it someday.



In the interm, you need to ensure that all exported components sanitize their inputs, no matter what those inputs are. Blindly assuming that Intent inputs are valid may be hazardous to your user’s health.

 •  0 comments  •  flag
Share on Twitter
Published on September 11, 2013 22:39

September 9, 2013

PSA: Think About Stronger App Signing Keys

Back in the beginning of Android development, we were told to use keytool to generate our production signing key for our APKs. The only real requirement was that the key have a long enough validity period (25 years at the time, IIRC).



Now, the documentation for app signing contains a small side note about the -keysize parameter to keytool:




The size of each generated key (bits). If not supplied, Keytool uses a default key size of 1024 bits. In general, we recommend using a key size of 2048 bits or higher.




The reason for the 2,048-bit key size recommendation is that 1,024-bit RSA (the keytool default) has been considered at risk for a few years.



The recent revelations about state-sponsored decryption research should be hammering this home. Even if today, forging a 1,024-bit digital signature is still impractical for all but the largest security agencies, it is well within reason that this will fall within the reach of large botnets in the not-too-distant future. As with the “master key” security issue from earlier in 2013, apps will be able to be replaced with hacked editions, without tripping up the signature check, or signature-level permission checks might start passing due to forged signatures.



Switching to a larger keysize is not that hard… for new apps. Just specify -keysize 4096 when creating your production signing key, and you should be good for a long time, barring a major decryption breakthrough for RSA signatures.



For existing apps with existing signing keys, though, you cannot change the key without breaking your ability to update the app — the very security measure we are trying to ensure works will stop us.



Unfortunately, one survey has found that ~75% of Android apps use 1,024-bit signing keys. That includes me, as I had created a production signing key before the documentation update and had missed the update itself, since the security point was not trumpted by Google.



Hence, I’m doing my own bit of trumpeting. Fortunately, without a trumpet, as I don’t play the trumpet, and it is a bit early in the morning for my neighbors to have to put up with amateur trumpet-playing…



Create a new, stronger production signing key, as a separate key from whatever you are using for production. Make note to use that new signing key for any new apps you create. And, if you have other reasons why you are migrating an existing user base to a new app (e.g., free app for which you are now offering a paid-app option), consider using the new signing key.



If you are a consultant, and you create unique signing keys per project, just cut over to using a stronger key for new clients and projects.



And if you are creating apps for which security is paramount, you might consider whether it is worthwhile to move your user base to a new version of the app with a new signing key at some point.



A tip o’ the hat to The Guardian Project, whose mailing list posts pointed out this issue.

 •  0 comments  •  flag
Share on Twitter
Published on September 09, 2013 08:58

September 6, 2013

Raising My Game on Security

It is fairly obvious, given the revelations of recent days and weeks, that the security we developers thought we had built is not as strong as it should be.



Whether you find the behavior of the NSA and GCHQ to be exemplary or execrable, if they can break through this security, others can too. The GCHQ does not have a monopoly on brains, and the NSA has amply demonstrated that others can get at the NSA’s own data. While you may agree with the NSA’s and GCHQ’s professed aims, it is unlikely that you would agree with the aims of everyone potentially capable of breaking security, whether they be state-sponsored agencies, organized crime, rather disorganized crime (e.g., you left your phone in the back of a taxi), etc.



While there will be shouts and cries in Whitehall and Washington for legislative and judicial controls over global surveillance, it is really up to us as engineers to “raise our game” and better secure the endpoints, given that the security of the pipes and centralized services is suspect.



And, right now, Android may well be the most popular endpoint OS on the planet.



So, here is how I will be raising my game:





Continuing to expand coverage of security measures in my book, such as validating app signatures, blending strong SSL techniques with HTTP stacks like Retrofit, etc.





Continuing to add code samples on the coverage that is already there, such as SSL certificate pinning and memorization, encrypting GCM messages, etc.





In 2014, revising my book tutorials — and other samples as is practical — to use SSL and encrypted databases





Building more open source libraries with an eye towards security (anyone want a FileProvider workalike that supports serving encrypted files?)





Continuing to present on defending user data, at conferences and elsewhere





Donating to projects like Trsst, as even if the Web site winds up failing in the marketplace of services, the open source secure-and-federated architecture may succeed in the marketplace of ideas





Even finally getting SSL going on the Warescription site (not that there’s much to secure at present)





And I have some other “irons in the fire” for 2014 and beyond.



How are you going to raise your game?

 •  0 comments  •  flag
Share on Twitter
Published on September 06, 2013 20:31

September 5, 2013

The CommonsGuy 2013 Whirled Tour

I am delivering a dizzying array of presentations in October and November. Hence, the Whirled Tour!



First up, in my home territory, I am presenting at the October 15th edition of the Lehigh Valley Tech Meetup. This presentation is for newcomers to Android, offering a “20,000-foot view” of what app development is like, both using the traditional Java-and-XML approach and alternatives like hybrid apps and NDK-style native coding.



Next, I am supposed to be presenting on October 16th at Android Alliance Philadelphia, though we are still working out a topic and therefore I have no direct link to the event.



I then float across the Atlantic on a raft made of KitKat® bars, rolling on up the Thames to London. Or, possibly, I’ll fly — I am still doing research on the behavior of milk chocolate in salt water.



On October 23rd, I will be giving a brief presentation on Android threading at Apps World Europe, in one of the sequentially-numbered Earl’s Court halls.



Also on October 23rd, I am letting you “In the Brain of Mark Murphy” at Skills Matter’s office. My brain is frequently rather untidy, so I apologize in advance for the mess. Specifically, though, I will be presenting on “Mastering the Master-Detail Pattern”.



On October 25th, I will be watching awesome presentations from the likes of Jeff Gilfelt, Juhani Lehtimäki, Hans Dockter, Mark Allison, and many more at droidcon UK. I’ll also be chipping in with “Android Security: Defending Your Users”, with an emphasis on “low-hanging fruit” solutions like SQLCipher for Android.



From there, I head to San Francisco, where I will be helping out with the Samsung Developer Conference. I’m scheduled to present “Secondary Screen Support Using DisplayManager”, though I cannot prove this, as their site is not listing the presenters just yet. Also, I have been told that registrations end September 6th, so if you were considering attending, do not let the grass grow under your feet. For starters, that stuff tickles.



After that, I take a break for a couple of weeks, before returning to the Bay Area for AnDevCon San Francisco 2013, the fifth(?) time that I have attended and presented. There, I will be reprising my “Mastering the Master-Detail Pattern” presentation, plus delivering “The Action Bar, Front to Back”, in addition to attending presentations by the likes of Christian Kurzke, Matt Kranzler and Matt Runo, Geoff Matrangola, and many others. Of course, both of my presentations are opposite ones delivered by Googlers, so I may be able to sneak out of my empty presentation rooms and watch theirs… :-)



And, I may have other presentations popping up in this timeframe, so stay tuned to the CommonsWare home page for the latest scheduled events.

 •  0 comments  •  flag
Share on Twitter
Published on September 05, 2013 05:01

September 4, 2013

The Busy Coder's Guide to Android Development Version 5.1 Released

Subscribers now have access to the latest release of The Busy Coder’s Guide to Android Development, known as Version 5.1, in all formats. Just log into your Warescription page and download away, or set up an account and subscribe!



This update contains:





A new chapter on Android 4.3’s restricted profiles and their impacts on your app





The beginnings of a new chapter on MediaStore, with this update focusing on finding videos and retrieving information about them, including thumbnails





A new chapter on the AppCompat action bar backport





A new chapter on Android development using IntelliJ IDEA





Coverage of additional Android 4.3 bits, particularly the WakefulBroadcastReceiver and FileProvider





Updated coverage of the clipboard, including a discussion of the Android 4.3 clipboard bug





Updates to the latest SQLCipher, OkHTTP, Retrofit, and Picasso for their various samples





Reference to the giggle-inducing -xxxhdpi resource set qualifier





Miscellaneous updates and errata fixes





I am projecting Version 5.2 to be released in mid-October, barring a early release of a confection-named Android update.



If you have any problems accessing your update, be sure to let me know!.

 •  0 comments  •  flag
Share on Twitter
Published on September 04, 2013 04:37