Security of sending sensitive intent extras within my own app? - android

I have an activity which asks for a username and password, then starts another activity in my app to complete a user signup. I want to send the username+password as intent extras to the second activity. Something like:
Intent intent = new Intent(activity, SecondActivity.class);
intent.putExtra("u", username);
intent.putExtra("p", password);
startActivity(intent);
and my manifest defines SecondActivity like:
<activity
android:name="com.me.SecondActivity"
android:label="">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.me.FirstActivity" />
</activity>
and now I'm having doubts about the security of sending the username+password as intent extras like this - is it possible for another app to intercept the invocation of SecondActivity with a spoofed intent filter? Besides that, I wonder what happens with the intent extras, are they ever persisted to disk by the OS? Someone might be able to look at them there if so.
Thanks

The key here is the distinction between Implicit Intents and Explicit Intents. Your example uses an Explicit Intent as your are specifying the exact class your want to run. This is fine, because Explicit Intents cannot be intercepted and will stay within your application.
Implicit Intents however, open up several possible attack vectors. This article talks about it in more detail. I would very much recommend against using Implicit Intents to pass any kind of sensitive information.
From the Android Docs:
Explicit Intents have specified a component (via setComponent(ComponentName) or setClass(Context, Class)), which provides the exact class to be run.
Implicit Intents have not specified a component; instead, they must include enough information for the system to determine which of the available components is best to run for that intent.
As I stated, for your example in the question, passing the password via Intent is relatively secure in that no other application can intercept it at runtime. But it is important to note that this is not always the case, and using implicit Intents could theoretically allow Intent Interception and expose the sensitive information.
Edit:
As for persisting the Intent Extras to the disk, yes this is a risk. Keep in mind however, that if someone has root access on the device and is using it to try to search the disk for this persisted intent information, there may be easier ways for them to get the same information. No matter what you do, someone with root access to the physical device will probably be able to get that password off unless you do some very excellent encryption.
My recommendation on a overall security perspective is to try not to deal with passwords directly in any kind of long term or persistent context. Passwords should only be used during a log in process and discarded immediately afterwards (assuming you are authenticating with a server). Therefore, with the normal use of the application (a legitimate user with a real password), you don't have to worry about a malicious actor inspecting the device memory, because by the time the malicious actor gets a hold of the device, the password has long sense been removed from memory.

It is possible for third-party apps to intercept system-wide intents. I suggest encrypting your data before sending it to the next intent, and then decrypting it once it has been received.

Handling passwords should always be a very short term affair. It's recommended to use them only for authentication request and then discard them. Coming to specifics of your question, i.e., sending password between activities through an explicit intent, this is secure to the extent that no other app will be able to intercept it and view the value. However, the passwords value needs to be maintained somewhere (memory or disk) in order to pass it to your secondary activity. If it's maintained on the disk it's pretty easy to retrieve. If its maintained in memory, an attacker who gets access to your device can root it and then perform memory dump to view the values in the memory. Thus it is not recommended to deal with passwords in this fashion.

Related

Security of critical data passing between activities via intent extras

I wonder if it is a bad idea to pass critical data between application's activities via intent extras.
For example, assume an application have 2 activities: A and B. Activity B will be started by A and A passes some critical information such as password via an intent extra when starting B.
I wonder if this is a dangerous or bad practice in android. For example, can such an approach leak password to other apps? Is there any better way to do so? Generally, do you know any good reference for learning about bad practices in android coding?
Assuming that you're referring to intents that just start specific Activities, I think you don't need to worry too much.
To take advantage of sensitive information in such intents, attacker will need to do at least one of the following:
Find a bug in Android framework that can be exploited
Upload custom ROM with malicious additions to user's device without user noticing
Upload application APK with malicious additions to user's device without user noticing
While all these scenarios can theoretically happen, I wouldn't bother to safe-guard against them in most cases.

Is data transfer between Android applications secure?

I can call other apps' Activities without problem, including sending them some data and receiving some data back. But I am sending and receiving some sensitive information that could arguably be misused if in the wrong hands. My question is, is this data safe when traveling between appications?
For example, I call an Activity like this:
Intent intent = new Intent("com.my.package.MY_REQUEST_ACTION");
intent.setClassName("com.other.package", "com.other.package.UserActionActivity");
signerIntent.putExtra("INTENT_PASSWORD", "1234");
signerIntent.putExtra("INTENT_COMMAND", "COMMAND_DO_SOMETHING");
signerIntent.setType("text/plain");
startActivityForResult(intent, 0);
And return something in UserActionActivity:
Intent result = new Intent("com.other.package.INTENT_RESULT_DESCRIPTION");
result.putExtra("INTENT_RETURN_RESULT", "...");
result.putExtra("INTENT_RETURN_RESULT2", "...");
setResult(Activity.RESULT_OK, result);
finish();
And so on. But how secure are these extra strings? Do I have to worry about them being accessible to other applications (other than the two involved), either intentionally or through some kind of "hack"? Do I need something like public key encryption?
And is the situation different on rooted systems (i.e. an app with root privileges can, without too much effort, read inter-app communication)?
Do I have to worry about them being accessible to other applications (other than the two involved), either intentionally or through some kind of "hack"?
Let's assume for the moment that neither app has been modified by an attacker.
If so, then in principle, the communications that you have established should be private on non-rooted device. In practice, there have been bugs with activity Intent extras, though none that I know of recently. Of your IPC options, activities are probably the worst choice from a security standpoint, as they have other impacts (e.g., appear in the overview/recent-tasks screen) that increase the likelihood that there is some bug that we have overlooked.
In your code, though, both sides assume that the other app has not been modified. In particular:
Unless you have some security that is not shown, any app on the device can run the code in your first snippet and try to trick the app to return the response in the second snippet.
The code in your first snippet assumes that com.other.package has not been modified by an attacker.
There are ways to help defend against this (e.g., custom signature permissions, checking the signature at runtime).
Also, bear in mind that an attacker can find "1234" without much difficulty.
With regards to the comments advising encryption, given the protocol that you are describing, encryption seems like an unlikely solution. If you have to provide a secret (INTENT_PASSWORD) in the IPC protocol, then there is no shared secret that both apps would have to use for encryption purposes, and I'm not quite certain what public-key infrastructure you would use to offer public-key encryption here.
And is the situation different on rooted systems (i.e. an app with root privileges can, without too much effort, read inter-app communication)?
Absolutely. On a rooted device, all bets are off. That is not tied specifically to IPC, though.
short answer: it is not safe but it needs some effort for the attacker.
long answer:
the transfer can be intercepted by a man in the middle attack:
on unrooted phones:
if you send data to intent.setClassName("com.other.package", "com.other.package.UserActionActivity"); somone can uninstall the original "com.other.package" and install his own "com.other.package" with the same activity that receives the unencrypted data.
For example an attacker can disassemble the original software, add code (that does something with the secret data) and reassemble the code to a new apk (with a different certificate)
On rooted devices: I donot know but i assume it is possible that the "exposed framework" is capable to intercept and redefine android os calls.

How can I securely transmit data between applications

I want to transmit a small amount of data between a Service and an Activity. These are separate applications. Ideally, I'd just pack my data (and a nonce for confirmation) into an Intent and use that. But per Mark Murphy's blog post Warning: Activity Intent Extras Can Be Public I know this is not safe.
Is ResultReceiver safe?
Is there a better way to do what I want?
Here is my use case:
Service A is going to launch Activity B with an Intent and ask the question "Is operation X authorized?". User action may be required, so that's why I'm launching an Activity from a Service.
I want Activity B to answer simply "yes" or "no". I want to make sure a malicious app on the device can't spoof that response. My current code uses an Intent to send the response.
I'm taking a defense-in-depth approach, and part of that is that I don't want the request from A to B to be readable by anybody else. Among other things, I intend to pack a nonce into the original request
Answering #mwhs' questions:
Service is only asking a yes/no question. I want to be very sure that the response comes from who I'm expecting it from. A nonce should do the trick, but it would need to be transmitted securely.
I'm not a security expert other than a little dabbling. What do you mean by "receipt of that very nonce on the initial sender side must carry a proof, that the intended party actually replied with that nonce, ideally by binding the nonce (or a decrement of it) cryptographically to a proof of identity (which can be usage of a shared good key for instance)"?
Assuming I can get the nonce securely to the other party, doesn't the fact that the other party responds with it constitute proof that they're the intended party? How do I "bind" the nonce to proof of identity? Some sort of HMAC? And why decrement it; is that some sort of hash-buster?
I'm a little leery of embedding shared secrets into an app that could theoretically be reverse-engineered.
Service A is going to launch Activity B with an Intent and ask the question "Is operation X authorized?". User action may be required, so that's why I'm launching an Activity from a Service.
For ordinary apps on ordinary devices, this is not a recommended approach, unless you are damn sure that the user won't regret you taking over the foreground with your activity.
I want Activity B to answer simply "yes" or "no". I want to make sure a malicious app on the device can't spoof that response.
The blog post that you cite refers to a bug that used to exist in Android, for extras packaged on an Intent used for startActivity(). Your scenario, as described, does not involve this, as you did not mention any extras on the Intent passed from Service A to Activity B. Plus, that bug has since been fixed, though I forget exactly where in the 4.x series it was fixed.
My current code uses an Intent to send the response.
That's not a particularly informative statement. That's akin to saying that you use a string to send the response. A string or an Intent may be the format of the response, but somehow you need to use inter-process communication (IPC) to get that response back to Service A.
One non-option is startActivityForResult(), as that is only available to activities, not services.
Possible IPC options include:
Calling startService() on the service, passing the Intent, using a custom signature permission to ensure that only your apps can call startService() on that service.
Calling bindService() on the service, waiting to get the binder, then passing the Intent (or whatever) to some method that you implement on the Binder (and using the same custom signature permission as above).
Passing a PendingIntent from Service A to Activity B as an extra, and having Activity B fill and execute that PendingIntent. You would use a signature permission or validating the signing key of Activity B's app to ensure that Service A only sends this to the correct app. And, you'd need to research the exact point when the problem that I outlined in the blog post got fixed.
Passing a ResultReceiver from Service A to Activity B (which otherwise works much as would the PendingIntent scenario above)
Having Service A register a BroadcastReceiver via registerReceiver(), then have Activity B send a broadcast matching the receiver's IntentFilter. You would need to go the custom signature permission route.
Doing something outside the Android component system (e.g., using an HTTP daemon in the service that the activity talks to). Ick.
Note that custom permissions suck, at least before Android 5.0.
Other than the now-fixed recent-activities Intent leak, I am not aware of any current means for spying on IPC, except:
rooted devices
custom ROMs
impersonation (e.g., Service A talks to Activity M from a malware author that is masquerading as Activity B)
The latter scenario is where signature permissions or validating the signing key of Activity B's app come into play.
Anything that is exported (scenarios #1, #2, #5) is at risk of spoofing. signature permissions help, except that custom permissions suck. I would lean towards #3 or #4.
Depending on what other communications are going on between these apps, there may be other options (e.g., long-term bound service, with callback objects to provide bi-directional communication).

Using Intents as a form of message passing

Are there any drawbacks to using intents as a form of message passing between two apps that I control?
I have two apks which will always exist on the device together. And, I'd like to use explicit intents to pass messages back and forth as opposed to creating and managing two separate services. Using explicit intents just seems like an easier to manage approach than services.
Communication between applications can expose certain rich, but if you really need to do this way, you can only customizing permissions that your applications will have knowledge. Then you can use BroadcasrReceiver to exchange messages securely using custom permissions.
Defining their permission:
<permission android:name="com.yourapp.PERMISSION"
android:protectionLevel="signature"
android:label="#string/permission_label"
android:description="#string/permission_desc">
</permission>
By setting
<receiver android:name=".MyReceiver"
android:permission="com.yourapp.PERMISSION">
<intent-filter>
<action android:name="com.yourapp.ACTION" />
</intent-filter>
</receiver>
In addition to these permissions you can also set them their purchases Activities, Services, ContentProvider.
Edited
Integration between existing processes in Android (Inter-Process Communication), the AIDL (Android Interface Definition Language).
AIDL is particularly useful when different applications need to
communicate among themselves to exchange information through a
well-defined interface with support for multithreading. Unlike the use
of Messenger with Bound Services with AIDL you are required to create
a file. AIDL containing the declaration of the integration interface,
which helps the client applications to know which operations are
available as well as their respective arguments and returns.
You can use intents to pass data between two apps..however I see once drawback(not too big)-you need to take care that those intents dont get exposed to others.Some malicious app can use the same intents to send bad data something similar to Denial-of-service attacks.
Just to add-if the interactions are in background you can use broadcast receivers too.
Also if the apps are always going to be together why are you not packing them as single app.If you are using parcelables, your flow might break if there are two different incompatible versions of the parcelable.(if you add a field to a object in new version of an app,the other app is still not updated,the app might crash).
Although the discussion here seems really good, at #André.C.S's suggestion, I will add my 2 cents.
Intents are a simple and effective way of passing messages between processes. One of Android's key features, the ability to call another application as a function (Activity.startActivityForResult), depends on it.
As everyone here has already pointed out, intents, whether fired at BroadcastReceivers, Services or Activities, have security issues. If you decide to use them, you will need to protect them. Andre's description of how to use permissions to do that is spot on. You must treat the method that catches the intent as if it were a web service and verify parameters, etc. accordingly.
Finally, Intents, while simple, are really not appropriate for high-bandwidth IPC. If you will be exchanging messages with the other app at a rate measured in milli-seconds, you will want to look into AIDL and a bound service. By my measurements, they are between 1 and 2 orders of magnitude faster.
Incidentally, you might consider running both applications in the same process. There are manifest application attributes that allow that. If you did that, using explicit intents would be easy and your apps would be much safer.
Edited to point out extremely embarrassing error
So, taking my own advice, I tried it. To my horror, as several people have tried to point out, explicit intents can be used across processes.
I am eating a large helping of crow, with humble pie for dessert.
An explicit intent contains a ComponentName object, not an explicit reference to a class object, as I claimed. A ComponentName contains a package name and a class name. The former is, typically, derived from the current context and thus is local to the current process. It is possible, however, to construct an intent with a package name that is an arbitrary string.
I stand corrected.

Get calling context in a service

So I'm working on a service that will handle requests to send data to a socket.
I've done socket programming in a service before, but only within the same application. I'd like this to just sit and do nothing until any application wants to give it data to send. That's all well and good.
I have register an intent filter and the usual stuff and can process the data. But I want to process the data coming from different activities in different threads (subsequent calls from the same application will be computed on the same thread).
Is there a way to get the calling package or app or whatever? I'd prefer not to require passing in an identifier as an extra to prevent spoofing. (It's not a serious security concern, it's just each application needs its data processed in the order that it's received.)
I had run to the same issue in the past. I couldn't find a way to know how send the intent and I ended up adding an extra.
If you don't want to use an extra perhaps you might want to set an Action but it's almost the same thing.

Categories

Resources