You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

Android applications' core components such as activities, services, and broadcast receivers are activated through messages, called intents. Applications can use broadcast to send messages to multiple applications (i.e., notification of events to an indefinite number of apps). Also, an application can receive a broadcast intent sent by the system.

To broadcast an intent it is passed to Context.sendBroadcast() to be transmitted and interested receivers can receive the intent, dynamically registering themselves by calling Context.registerReceiver() with the specified intentFilter as an argument. Alternatively, receivers can be statically registered by defining the <receiver> tag in the AndroidManifest.xml file.

When sendBroadcast() is used, normally any other application, including a malicious application, can receive the broadcast. Therefore, receivers of broadcast intents should be restricted.

One way to restrict receivers is to use an explicit intent. An explicit intent can specify a component (using setComponent(ComponentName)) or a class (using setClass(Context, Class)) so that only the specified component or class can resolve the intent.

It is also possible to restrict the receivers of intents by using permissions, as described below. Alternatively, starting with the Android version ICE_CREAM_SANDWICH, you can also safely restrict the broadcast to a single application bu using Intent.setPackage().

Yet another approach is to use the LocalBroadcastManager class. Using this class the intent broadcast it never going outside of the current process. According to the Android API Reference, LocalBroadcastManager has a number of advantages over Context.sendBroadcast(Intent):

  • You know that the data you are broadcasting won't leave your app, so don't need to worry about leaking private data.
  • It is not possible for other applications to send these broadcasts to your app, so you don't need to worry about having security holes they can exploit.
  • It is more efficient than sending a global broadcast through the system.

Noncompliant Code Example

This noncompliant code example shows an application (com/sand/airdroid/ServerService.java) with a vulnerable method d() using an implicit intent v1 as an argument to this.sendBroadcast() to broadcast the intent. The intent includes such sensitive information as the device's IP address (local_ip), the port number (port), and the password to connect to the device (code).

public class ServerService extends Service {
  // ...
  private void d() {
    // ...
    Intent v1 = new Intent();
    v1.setAction("com.sample.action.server_running");
    v1.putExtra("local_ip", v0.h);
    v1.putExtra("port", v0.i);
    v1.putExtra("code", v0.g);
    v1.putExtra("connected", v0.s);
    v1.putExtra("pwd_predefined", v0.r);
    if (!TextUtils.isEmpty(v0.t)) {
      v1.putExtra("connected_usr", v0.t);
    }
  }
  this.sendBroadcast(v1);
}

An application could receive the broadcast message by using a broadcast receiver as follows:

final class MyReceiver extends BroadcastReceiver {
  public final void onReceive(Context context, Intent intent) {
    if (intent != null && intent.getAction() != null) {
      String s = intent.getAction();
      if (s.equals("com.sample.action.server_running") {
        String ip = intent.getStringExtra("local_ip");
        String pwd = intent.getStringExtra("code");
        String port = intent.getIntExtra("port", 8888);
        boolean status = intent.getBooleanExtra("connected", false);
      }
    }
  }
}

Proof of Concept

An attacker can implement a broadcast receiver to receive the implicit intent sent by the vulnerable application:

public class BcReceiv extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent){
    
    String s = null;
    if (intent.getAction().equals("com.sample.action.server_running")){
      String pwd = intent.getStringExtra("connected");
      s = "Airdroid  => [" + pwd + "]/" + intent.getExtras();
    }
    Toast.makeText(context, String.format("$B!V(B%s$B!W(BReceived", s),
                   Toast.LENGTH_SHORT).show();
  }
}

Compliant Solution

If the intent is only broadcast/received in the same application, LocalBroadcastManager can be used so that, by design, other apps cannot received the broadcast message, which reduces the risk of leaking sensitive information.

Instead of using Context.sendBroadcast(), use LocalBroadcastManager.sendBroadcast():

Intent intent = new Intent("my-sensitive-event");
intent.putExtra("event", "this is a test event");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

Risk Assessment

Using an implicit intent can leak sensitive information to malicious apps.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

DRD03-J

High

Probable

Medium

P12

L1

Automated Detection

Automatic detection of the use of Context.sendBroadcast() is trivial. It is not feasible to automatically determine whether LocalBroadcastManager.sendBroadcast() can be used instead.

Related Vulnerabilities

  • JVN#67435981 LINE for Android vulnerable in handling of implicit intents
  • JVN#42625179 Loctouch for Android vulnerable in handling of implicit intents

Related Guidelines

JSSEC Android Secure Design and Secure Coding Guidebook

4.2.2.5. To broadcast sensitive information, restrict the corresponding receivers

Bibliography

Android Secure Coding Guidebook by JSSEC

 4.2.2.5. To broadcast sensitive information, restrict the corresponding receivers

 

 

  • No labels