Search code examples
androidalarmmanagerandroid-alarmsandroid-broadcastreceiver

AlarmManager and WakefullBroadcastReceiver how private are the passed Extras?


I am trying to implement some alarm scheduling by using AlarmManager. Since when a alarm is triggered, I want to use a WakefulBroadcastReceiver which starts an IntentService to do some background job.

I have some questions related to security/privacy of the parameters passed for alarm's intents.

  1. When setting a PendingIntent for a alarm I do something like:

    Intent myIntent = new Intent(context, MyReceiver.class);        
    myIntent.putExtra("test", "testValue");
    Bundle bundle = new Bundle();
    bundle.putParcelable("bundleValue", bundleTestValue2);
    myIntent.putExtra("test3", bundle);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 323,
        myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    

My question is: how private are the values set as Extra for the pendingIntent of the alarm? Is there a chance of them getting read by some other app since is being used by Android Alarm's Manager after it is scheduled?

  1. By having a receiver like

    public class MyReceiver extends WakefulBroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
           startWakefulService(context, MyIntentService);
    }
    

And on android manifest

 <receiver
            android:name=".receivers.MyReceiver"
            android:exported="false"/>

 <service 
          android:name=".MyIntentService" 
          android:exported="false"/>

And the service

public class MyIntentService extends IntentService {

  @Override
  protected void onHandleIntent(Intent intent) {

     try {
          //logic here
     } catch{
     } finaly{
          MyReceiver.completeWakefulIntent(intent);
     } 
}

Call from within my Activity

sendBroadcast(new Intent(context, MyReceiver.class).putExtra(...);

Schedule a pending intent from an alarm

Intent myIntent = new Intent(context, MyReceiver.class);        
myIntent.putExtra("test", "testValue");

PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 323,
    myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

how exposed is this receiver to other apps? Can it react to other apps except mine? Does this rise any security possible issues?

Thank you.

Later edit: Since the WakefullBroadcastReceiver seems the only way that guarantees that my service will get a partial wakelock, how can I make sure 100% that no other apps will be aware of my receiver and that my receiver won't get any other calls except ones made from my activity or from my set Alarm?

How would a WakefullBroadcastReceiver pattern works versus CommonsWare's WakefulIntentService ?

Later Edit: I've finally managed to finish my implementation.

  1. As stated before, both my WakefulBroadcastReceiver and IntentService are declared as exported="false" in my Android Manifest which from what I understand means that only my app can access them. Since the receiver is not exported, does it receive broadcasts from outside the app?

  2. When setting an alarm I use this PendingIntent:

    Intent myIntent = new Intent(context, MyReceiver.class);
    myIntent.putExtra("databaseId", "1"); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 323, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

  3. When calling from my Activity I do:

sendBroadcast(new Intent(context, MyReceiver.class).putExtra("databaseId", "1"));

Is this enough?


Solution

  • Privacy considerations related to Intent extras

    In general, I would say that it is an insecure practice to put sensitive data in Intent.

    In theory, if Intent can only be consumed by specific application (discussed later) then only that application should be able to see its contents. However, given a vast amount of Android devices and OS versions (incl. rooted devices and custom ROMs), I wouldn't count on it.

    You did not specify the kind of sensitive data you'd like to pass in Intent extras, therefore I can only give these general recommendations:

    1. Make sure you understand the "confidentiality level" of the data in question: is it secret, or just restricted? Or, maybe, it is public (in which case no protection needed)?
    2. Try to find another approach that doesn't involve passing sensitive data in Intent (I myself never encountered such a need).
    3. If you absolutely must pass sensitive data in Intent extras - consider encrypting it. The encryption model should be adequate to "confidentiality level" of the data, and to potential harm which could be done if that data is being intercepted (it can go all the way up to "server side" encryption).

    Privacy/security considerations related to BroadcastReceiver

    In general, BroadcastReceiver is a component which receives "system wide" broadcasts. The fact that the broadcasts are "system wide" should speak by itself about the level of privacy associated with them.

    That being said, there is one mechanism by which developers can restrict broadcasts' scopes: custom permissions. Usage of custom permissions allows for two "levels of control" over broadcasts:

    1. If broadcast requires specific permission then only if BroadcastReceiver has that permission will it receive the broadcast.
    2. If BroadcastReceiver filters the incoming broadcasts by specific permissions, then only broadcasts carrying that permission will be delivered to that receiver.

    While the above points can seem similar on the first sight, these are distinct schemes that can be used separately, or combined. The first scheme associates a broadcast with a permission (and the sender of that broadcast doesn't necessarily have that permission by himself), while the second scheme filters all broadcasts by specific permission (and the receiver must have that permission).

    A better approach in your case

    EDIT: this COULD BE a better approach if "wakefullness" wouldn't be part of the requirements. But it is. Since there is no guarantee that Service started by AlarmManager will get a chance to acquire a wake lock - this approach is not suitable for OP's case.

    Please note that broadcasts and custom permissions were designed in order to introduce "decoupling" at application level - this scheme allows for sender application to be completely agnostic of the receiving application, as long as they agree on one custom permission (well, the same scheme is employed for pre-installed public permissions as well, but you wouldn't want to guard your sensitive data with a public permission).

    In your case, however, sender and receiver are the same application. In such setting you don't really need all the trouble associated with broadcasts - just construct PendingIntent that starts the required Service inside your app, and you get it all at once:

    • PendingIntent and the associated Intent start a specific Service in your application (by name), therefore no other application can intercept it (theoretically, remember the above discussion).
    • Target Service can be non-exported, therefore no other application can access it in any way.

    You welcome :)