Protecting extra data in Android Intent
Asked Answered
O

3

7

I'm using an Intent to start a new Activity in a new task. This Intent carries some private data needed by that Activity in its extras. This data should not be readable by other applications. We've investigated whether this data is indeed not leaked. We found out that by using RecentTaskInfo from getRecentTasks() this extra data is readable by any arbitrary application that has GET_TASK permission. This is not very secure. We've stopped searching once we found this leak. Are there more ways this data is leaked? And, how can I ensure the data in the extra is not readable by other applications?

Onetime answered 19/3, 2013 at 13:46 Comment(0)
B
8

Starting from Android 4.1.1 an additional permission was added to guard extra's being read by third party apps using the RecentTaskInfo. This permission (android.Manifest.permission.GET_DETAILED_TASKS) can only be acquired by the system. Without this permission, the extra's will be swapped out before the baseIntent is returned via the RecentTaskInfo.

From the comment of commit http://androidxref.com/4.2.2_r1/history/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java#8238e717df4bc5eebf15f97172d68af3599a95bb:

Add new signature-level permission to get details of tasks.

Third party apps now can't get access to the extras of the intents associated with tasks, to keep private data in them from leaking out.

Change-Id: I95af9e181ac42557bc8b981807e7ddd266a88d0e

So it seems that effort is being put into making intent extra's safer to transport sensitive information. I don't know if there are other ways in which these extra can leak, but at least the extra's seem OK from JB up.

Bedroll answered 19/3, 2013 at 14:14 Comment(1)
Well, that's certainly cool. I will have to investigate this further. Thanks!Kuwait
K
6

This Intent carries some private data needed by that Activity in its extras

Why? Pass identifiers to private data in extras, where resolving those identifiers into that private data (e.g., database query) can only be done by the activity.

We found out that by using RecentTaskInfo from getRecentTasks() this extra data is readable by any arbitrary application that has GET_TASK permission

Yes, I blogged about this nearly two years ago, and others probably did even before that.

Are there more ways this data is leaked?

All requests to start other components go by way of an OS process, and so the data is "leaked" to the OS all of the time.

And, depending on what you do with the Intent, you might leak it in other ways (e.g., pass an Intent itself, as a Parcelable, to other apps).

And, how can I ensure the data in the extra is not readable by other applications?

You can't. Again, do not put private data in activity extras, but instead use identifiers that can be used to get that private data.

Kuwait answered 19/3, 2013 at 13:55 Comment(4)
Although I agree that your solution can be used (and by the way, it will be applicable to "all" api levels), it seems that more recent versions of Android actually fix the issue described in your blog. Check the commit I linked in my answer..Bedroll
I can accept that the OS is able to read my data, the problem lies in non OS apps. If I interpret your solution correctly, it implies setting up a ContentProvider. That just moves the security issue to a different location: how to ensure that the query only returns an answer when the intended activity accesses it? I don't see permissions as a workable solution when multiple applications need to have secure information send to them but they are not allowed to see each others information.Onetime
@user2186703: "If I interpret your solution correctly, it implies setting up a ContentProvider" -- no. The concept of data having identifiers, like primary keys in database tables, has been around for decades. Since Android has not been around for decades, there have been ways of finding data using identifiers without using Android-specific constructs like ContentProvider. So, by "identifiers", I mean keys to your database table, or keys to your HashMap, or row numbers of your CSV table, or keys to your JSON object, etc.Kuwait
@user2186703: In case you were to implement this using ContentProvider, you could probably use the intent 'data' together with FLAG_GRANT_READ_URI_PERMISSION to give a uri-specific, one time read permission to the receiving activity, which can than retrieve the private data using a query. However, if you are ok with targeting JB+ you may want to consider sticking with your initial solution, since it appears to be safer than it was before Jellybean. (see other answer)Bedroll
A
1

You have private storage space, which is readable only by your application. On non-rooted devices, the information you store there will only be accessible to your app.

You could use a SharedPreference to store your data - the data is stored in your app's designated private storage.

Alternatively, you can use the private storage directly and wire arbitrary files there like this:

FileOutputStream fos;
try {
    fos = openFileOutput (FILENAME, Context.MODE_PRIVATE);
    fos.write (string.getBytes ());
    fos.close ();
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} 
Androecium answered 19/3, 2013 at 13:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.