Broadcast Receiver安全场景和危害

BroadcastReceiver是Android的四大组件之一,这个组件涉及两个概念:广播发送者和广播接受者。
这里的广播实际上指的就是intent。
当发送一个广播时,系统会将发送的广播(intent)与系统中所有注册的符合条件的接收者的IntentFilter进行匹配,若匹配成功,则执行相应接收者的onReceive函数。
发送广播时如果处理不当,恶意应用便可以嗅探、拦截广播,致使敏感数据泄露等;如果接收广播时处理不当,便可导致拒绝服务攻击、伪造消息、越权操作等。

Broadcast Receiver漏洞分类

  • 敏感信息泄露
  • 权限绕过
  • 消息伪造
  • 拒绝服务

敏感信息泄漏漏洞

发送的intent没有明确指定接收者,而是简单的通过action进行匹配。恶意应用便可以注册一个广播接收者嗅探拦截到这个广播,如果这个广播里存在敏感数据,就被恶意应用窃取了。

隐式意图发送敏感信息:

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);
    }
    sendBroadcast(v1);
}

POC:

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.makeTest(context,String.format("%sReceived",s),Toast.LENGTH_SHORT).show();
}

敏感信息泄露漏洞:修复

修复后代码,使用LocalBroadcastManager.sendBroadcast()发出的广播只能被app自身广播接收器接收。

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

权限绕过漏洞

可以通过两种方式注册广播接收器,一种是在AndroidManifest.xml文件中通过标签静态注册。另外一种是通过Context.registerReceiver()动态注册,指定相应的intentFilter参数。然而动态注册的广播默认是导出的。如果导出的BroadcastReceiver没有做权限控制,导致BroadcastReceiver组件可以接收一个外部可控url、或者其他命令,导致攻击者可以越权利用应用的一些特定功能,比如发送恶意广播、伪造消息、任意应用下载安装、打开钓鱼网站等。

程序加锁解锁是靠广播来控制的,并且这两条广播没做权限限制,任意应用可以发送此广播达到恶意解锁、恶意锁定应用的目的。

code:

android.intent.action.PACKAGE_FULLY_REMOVED

漏洞证明:

简单测试方法用adb shell 发送广播

code区域:

am broadcast -a android.intent.action.PACKAGE_FULLY_REMOVED -d package:com.wumii.android.mimi

权限绕过漏洞:修复

推荐使用呢LocalBroadcastManager类,这个类相较于Context.sendBroadcast(intent)有下面三方面的优势。

1.不用担心敏感数据泄露,通过这种方式发送的广播只能应用内接收。
2.不用担心安全漏洞被利用,因为其他应用无法发送恶意广播给你。
3.它比系统的全局广播更高效。

消息伪造

暴露的Receiver对外接收Intent,如果构造恶意的消息放在Intent中传输的,被调用的Receiver接收有可能产生安全隐患。  

Intent i= new Intent();
i.setAction("com.baidu.android.oushservice.action.MESSAGE");
Bundle b = new Bundle();
JSONObject jsobject = new JSONObject();
JSONObject custom_content_js = new JSONObject();
jsobject.put("title","百度云盘【漏洞你中奖了!】");

jsobject.put("descrption","");

//jsobject.put("url","http://bcscdn.baidu.com/netdisk/BaiduYun_5.1.0.apk");
JSONObject customcontent_js = new JSONObject();
customcontent_js.put("type","1");
customcontent_js.put("msg_type","resources_push");

消息伪造 防护

设置为签名验证
android:protectionLevel="signature"

<receiver android:name="com.umeng.message.UmengMessageBootReceiver" android:protectionLevel="signature">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

拒绝服务

如果敏感的BroadcastReceiver没有设置相应的权限保护,很容易受到攻击。最常见的是拒绝服务攻击。拒绝服务攻击指的是,传递恶意畸形的intent数据给广播接收器,广播接收器无法处理异常导致crash。

拒绝服务攻击的危害视具体业务场景而定,比如一个安全防护产品的拒绝服务、锁屏应用的拒绝服务、支付进程的拒绝服务等危害就是巨大的。

拒绝服务 防护

  • 空指针异常

  • 类型转换异常

  • 数组越界访问异常

  • 类未定义异常

  • 其他异常

    //Serializable:
    Intent i = this.getIntent();
    if(i.getAction().equals(“serializable_action”)){
    i.getSerializableExtra(“serializable_key”);//未做异常判断
    }
    //Parcelable:
    this.b=(RouterConfig)this.getIntent().getParcelableExtra(“filed_router_config”);//引发转型异常崩溃

谨慎处理接收的intent以及其携带的信息。
对接收到的任何数据做try catch处理,以及对不符合预期的数据做异常处理。

Broadcast安全防护

  • 私有广播接收器设置exported=’false’,并且不配置intent-filter。(私有广播接收器依然能接收到同UID的广播)。
  • 对接收来的广播进行验证。
  • 内部app之间的广播使用protectionLevel=’signature’ 验证其是否真是内部app。
  • 返回结果时需注意接收app是否会泄露信息。
  • 发送的广播包含敏感信息时需指定广播接收器,使用显示意图或者setPackage(String packageName)。
  • 使用LocalBroadcastManager。