Monday, 6 August 2012

Cross App Request Forgery in Android - CARF

An interesting thing about Android application security is that it is all very "What if?". Most scenarios I hear involve malicious apps. Malicious apps get installed by unsuspecting users and run in the guise of some innocent game whilst maliciously harvesting or installing other bits and pieces. The usual goal is to recover important data from another application or to use premium rate services or as botnets.
Normally the idea of malware specifically targeting other apps on a user's device would seem ludicrous but given the nature of some of the apps coming out on to the market place (sorry, Google Play), this seems more and more likely a vector in these more extreme cases.
This article has two points: The flaw in the root attack theory, and a potentially unthought of and certainly overlooked attack vector, the cross app request forgery (CARF)

Attacking an app with root.

I've often heard of a scenario in which malware elevates to root, and then attacks the flaws in the Manifest or file system of a specific app. Often android manifest writers overlook the fact that just because the action isn't exported it doesn't mean that it can't be run by other users. Root users may run all actions (including your precious providers), whether or not they are exported, unless they are explicitly not exported (exported=0x0).
But this is a bad argument for an attack vector. If you have root, why go after the app? You can access all the files, allowing you to grab the db files and everything else. If the db is encrypted, switch out the binary and trick the user into giving out the information you need to decrypt it. When you're done, switch the apps back, send off the data and disappear. This is far simpler to write (and portable to attack any app), than trying to pick apart and exploit specific vulnerabilities in others' apps.

Protecting against root?

When it comes to protecting against this vector there are three answers, keep the information off of the device (best), use the secure element, or encrypt information with a decent user entered password.
Keeping information off the phone means interacting with a server. Ideally the user sends up a hashed password, the server checks and responds with the information, allowing authentication and no chance for offline brute force attacks.
Secondly, the secure element is a purpose built secure vault with lock-out and no public bypasses. This is limited by having to partner with either a device (for an on-device secure element), or a network provider (if it's on the SIM).
Finally there's user passwords. These are used to encrypt the data on the file system. This is obviously limited as no one likes typing in long passwords on phones, and still vulnerable to social engineering.


The inability of many developers to control cross app communications securely leads to some unusual attack vectors. Normally these vectors are too complicated for the minimal rewards achieved for the amount of work, but given the nature of more high risk apps turning up on the market, the rewards are increasing.
An app may export several actions but it's careful only show up the login screen to outside attackers. Unable to login, the vector is closed right?
Well maybe. I was rather surprised on this one. Several apps developers are assuming that this is game over for the attacker and stop the protection there. I assume the point of this is that the phone user is using one app, passes some info across to the secure app at which point there is a prompt for password, limiting what information gets passed to only that which the user has permitted.
The issue is that if the user is already logged in, they are not prompted for their password. So if a user session exists, the doors are open to any app sending through information in this window. This could be done by an app without root permissions, so far more likely to make it through app store checks.
Either the app could try to indirectly monitor for when the app is in use, such as reading the log files, or just blindly hit the app every 5 minutes.


 Firstly Exported=0x0 is your friend. Everything should be explicitly not exported unless absolutely required.
 Secondly, always require user interaction before doing anything. Even validating the input before asking the user to confirm it allows for foreign arguments to be processed in your app. One mistake in this area of code means a vulnerability that could be exploited. If the user is using the phone, having one simple confirmation pop up won't hurt user experience, and scuppers the attack.