1. 问题说明

广播接收器 (Broadcast Recevier) 是一个专注于接收广播通知信息,并做出对应处理的组件。很多广播都是源自于系统代码,例如:电池电量低、通知时区改变、拍摄了一张照片或者用户改变了语言选项等等。当然应用程序也可以进行广播,例如,应用程序通知其它应用程序下载完成一些数据并处于可用状态。应用程序可以拥有任意数量的广播接收器以对所有它感兴趣的通知信息予以响应,所有的接收器均继承自 BroadcastReceiver 基类。广播接收器是没有用户界面的,但是它们可以启动一个 activity 来响应它们收到的信息,或者用 NotificationManager 来通知用户。如果 Broadcast Recevier 存在问题则可能被系统或者第三方的应用程序直接调出并使用。组件导出可能导致登录界面被绕过、信息泄露、数据库 SQL 注入、DOS、恶意调用等风险。

2. 测试步骤

检查 AndroidManifest.xml 文件中注册的 Broadcast Receiver,查找静态 Broadcast Receiver,反编译后检索 registerReceiver() 或者使用 drozer 命令 run app.broadcast.info -a APP包名 -i 来查找动态 Broadcast Receiver。注意检索 setPackage 方法与 receiverPermission 变量,查找发送广播内的信息检索 sendBroadcast 与 sendOrderedBroadcast,查看 onReceive 方法,检测是否存在信息泄露或拒绝服务的问题。

相关 drozer 命令如下:

  1. dz> run app.broadcast.info -a com.packagename
  2. dz> run app.broadcast.send --component com.packagename --action xxx.xxx.xxx
  3. # 我遇到的 onReceive 方法中使用 getSerializableExtra 时缺少异常处理机制,存在拒绝服务风险
  4. dz> run app.broadcast.send --action xxx.xxx.push.PenddingIntent

Broadcast Reciever - 图1

3. 修复建议

intent-filter 节点与 exported 属性设置组合建议:

  1. 私有广播接收器设置 exported=’false’,并且不配置 intent-filter。(私有广播接收器依然能接收到同 UID 的广播)
  2. 对接收来的广播进行验证;
  3. 内部 APP 之间的广播使用 protectionLevel=’signature’ 验证其是否真是内部 APP;
  4. 返回结果时需注意接收 APP 是否会泄露信息;
  5. 发送的广播包含敏感信息时需指定广播接收器,使用显示意图或者 setPackage(String packageName) ;
  6. sticky broadcast 粘性广播中不应包含敏感信息;
  7. Ordered Broadcast 建议设置接收权限 receiverPermission,避免恶意应用设置高优先级抢收此广播后并执行 abortBroadcast() 方法。