别让广播出卖你!Android BroadcastReceiver 漏洞排查全流程详解

别让广播出卖你!Android BroadcastReceiver 漏洞排查全流程详解

🚨Android BroadcastReceiver 漏洞排查全流程指南

🔐 面向 Android 安全新手,从 0 到 1 手把手教你排查 BroadcastReceiver 的安全风险!

✅ 什么是 BroadcastReceiver?

BroadcastReceiver(广播接收器)是 Android 四大组件之一,专门用来接收和响应广播消息,比如系统通知、电量变化、网络状态变化,或者 App 自己发的“登录成功”“支付完成”等消息。

它分为两种注册方式:

类型注册方式生命周期
静态注册写在 AndroidManifest.xml 中App 没打开也能接收
动态注册在代码中 registerReceiver()App 打开期间才生效

🔎 核心方法是 onReceive(),广播发出后就会触发这个函数运行你写的逻辑。问题就出在这里:

那攻击者就能伪造广播“骗你执行”——这就是广播欺骗、劫持、信息泄露等安全问题的根源。

✅ BroadcastReceiver组件的常见结构

📌 Manifest 中的注册结构示意:

 <receiver android:name=".MyReceiver"
           android:exported="true">
     <intent-filter>
         <action android:name="com.example.MY_ACTION" />
     </intent-filter>
 </receiver>

📌 BroadcastReceiver 的典型结构示意:

 // 1️⃣ 声明广播接收器类,继承 BroadcastReceiver
 public class MyReceiver extends BroadcastReceiver {
 ​
     // 2️⃣ 重写 onReceive 方法(广播的主要处理逻辑入口)
     @Override
     public void onReceive(Context context, Intent intent) {
         // 3️⃣ 获取广播 action 或参数
         String action = intent.getAction();
 ​
         // 4️⃣ 判断是否是预期的 action
         if ("com.example.MY_ACTION".equals(action)) {
             // 5️⃣ 执行对应的处理逻辑(如启动服务、记录日志等)
         }
     }
 }
 ​

🧭 Android 广播组件排查 3 步法

第一步:👀 快速识别有哪些广播接收器

🛠 Jadx反编译查看:

打开 AndroidManifest.xml,查找所有 <receiver> 组件:

 <receiver android:name=".DangerousReceiver">
     <intent-filter>
         <action android:name="com.vuln.EXEC_CMD" />
     </intent-filter>
 </receiver>

✅ 看点:

  • 有没有 android:exported="true"(或没写,Android11 以下默认也是 true)
    • 12及以上必须显型说明是True或False
  • 有没有设置 android:permission="..."(有则较安全)

🛠 Jadx全局搜索关键词:

关键词含义说明排查目的
onReceive实现广播接收的核心方法定位接收器逻辑入口
registerReceiver动态注册广播的 API查非 Manifest 注册的广播组件
sendBroadcast普通广播发送方法找出 App 主动发送的广播(可能泄露)
sendOrderedBroadcast有序广播发送方法分析是否存在劫持风险
abortBroadcast中断广播传递的方法判断是否有恶意阻断逻辑
Runtime.getRuntime().exec执行系统命令(高危)查是否被广播欺骗后执行命令
getStringExtra / getExtras获取广播参数查参数注入点或参数未校验位置
SmsManager.sendTextMessage发送短信 API(高风险)分析是否可被伪造广播诱发发送短信

排查建议:

  • 搜索结果中重点查看是否出现在 BroadcastReceiver 中,尤其是 onReceive() 方法内部。
  • 注意判断是否有 getStringExtra()intent.getAction() 等字段提取但未做校验。
  • 如出现 exec()、发短信等敏感操作,务必检查是否是被广播触发、是否加了权限控制。

第二步:🔍 分析每个接收器是否存在风险

📌 漏洞 ①:广播欺骗(Broadcast Spoofing)

✅ 风险描述:

攻击者伪造广播 Intent,触发敏感行为(如执行命令、发短信、启动服务)

☠️ 漏洞代码示例:
 public class DangerousReceiver extends BroadcastReceiver {
     @Override
     public void onReceive(Context context, Intent intent) {
         String cmd = intent.getStringExtra("cmd");
         try {
             Runtime.getRuntime().exec(cmd); // ⚠️执行任意命令
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 }
⚙️ Manifest 配置(无权限限制 + 默认导出):
 <receiver android:name=".DangerousReceiver">
     <intent-filter>
         <action android:name="com.vuln.EXEC_CMD" />
     </intent-filter>
 </receiver>
💥 ADB 利用命令:
 adb shell am broadcast -a com.vuln.EXEC_CMD --es cmd "touch /sdcard/pwned.txt"
📌 特殊适用条件:
  • 目标系统 Android 11 以下(12+ 默认要求 exported,查看是否有明确 exported = true
  • Receiver 没设置权限
  • 触发敏感 API(如 exec)

📌 漏洞 ②:信息泄露(Broadcast Leak)


✅ 风险描述:

应用通过普通广播(sendBroadcast(Intent))发送敏感数据,未对广播添加权限控制,导致任何安装在设备上的应用都能监听该广播并窃取敏感信息


⚠️ 有风险的配置和源码示例

发送方(泄露广播)代码示例:

 Intent i = new Intent("com.app.LOGIN_RESULT"); //com.app.LOGIN_RESULT 具体action
 i.putExtra("token", "user-token-123456");
 sendBroadcast(i); // ⚠️ 未指定权限,任何App均可接收
  • 这段代码中,调用了sendBroadcast,且没有传入权限参数。
  • 这样发送的广播是公开的,任何App都能通过注册相同action监听到。
  • 广播中附带了敏感字段token,暴露了用户信息。

Manifest 中未限制导出:

 <receiver android:name=".SensitiveReceiver" android:exported="true">
     <intent-filter>
         <action android:name="com.app.LOGIN_RESULT" />
     </intent-filter>
 </receiver>
  • 如果广播接收器本身导出(exported=true),意味着其他App也能发送该广播,增加风险。

👾 攻击者需要做什么?
  • 攻击者需要写一个恶意App,并安装到目标设备上。
  • 恶意App在AndroidManifest.xml中声明与目标App广播相同的action,并注册对应的BroadcastReceiver来监听广播。

攻击者的AndroidManifest.xml

 <receiver android:name=".Sniffer" android:exported="true">
     <intent-filter>
         <action android:name="com.app.LOGIN_RESULT"/>
     </intent-filter>
 </receiver>

攻击者的监听器代码:

 public class Sniffer extends BroadcastReceiver {
     @Override
     public void onReceive(Context context, Intent intent) {
         String leakedToken = intent.getStringExtra("token");
         Log.d("LeakedToken", "获取到的Token: " + leakedToken);
         // 这里可以将数据上传到服务器或做其他恶意操作
     }
 }

📱 是否可以通过 ADB 验证?
  • 不完全可以。

因为信息泄露需要安装恶意App来注册监听广播,普通的adb shell am broadcast只能模拟发送广播,无法直接模拟监听行为。

但你可以用ADB检查目标App发送的广播:

 adb shell dumpsys activity broadcasts
  • 该命令可查看当前系统广播队列,但不能直接看到广播内容和接收者。

要验证监听效果,必须:

  1. 编写一个简单监听广播的App(上面攻击者代码示例)。
  2. 安装到设备上。
  3. 运行目标App发送广播。
  4. 在监听App中观察日志(通过adb logcat)确认是否接收到敏感数据。

📌 特殊适用条件:
  • 目标App通过普通sendBroadcast发送广播且未设置接收权限
  • 广播内包含敏感数据(如Token、用户隐私信息等)。
  • 攻击者能在设备安装恶意App并注册对应广播监听器。

✅ 修复建议:
  • 发送广播时指定权限,只有拥有该权限的App才能接收广播:
 sendBroadcast(i, "com.example.PRIVATE_PERMISSION"); // ✅ 加权限
  • 并在 AndroidManifest.xml 中声明权限:
 <permission android:name="com.example.PRIVATE_PERMISSION"
             android:protectionLevel="signature" />
 ​
 <receiver android:name=".SensitiveReceiver"
           android:permission="com.example.PRIVATE_PERMISSION">
     <intent-filter>
         <action android:name="com.app.LOGIN_RESULT"/>
     </intent-filter>
 </receiver>
  • 或者通过动态注册的方式接收广播,限制注册范围,避免被其他App监听。

总结:
项目说明
发生场景发送敏感数据的普通广播无权限限制
攻击者条件安装恶意App监听目标广播
是否可用 ADB 验证只能查看广播状态,无法模拟监听
修复建议发送广播时加权限,声明权限限制

如果需要

 sendBroadcast(i, "com.example.PRIVATE_PERMISSION"); // ✅加权限

📌 漏洞 ③:有序广播劫持(Hijack)

✅ 风险描述:

攻击者通过设置更高优先级,拦截或阻断 sendOrderedBroadcast 发送的广播,修改或阻止原广播流程。

☠️ 恶意接收器配置:
 <receiver android:name=".HijackReceiver">
     <intent-filter android:priority="999">
         <action android:name="com.app.SAFE_ACTION"/>
     </intent-filter>
 </receiver>
 ​
 public class HijackReceiver extends BroadcastReceiver {
     public void onReceive(Context context, Intent intent) {
         abortBroadcast(); // ⚠️中断后续 Receiver
         // 或 setResultData("hacked") 修改内容
     }
 }
📌 特殊适用条件:
  • App 使用 sendOrderedBroadcast()
  • 目标系统 Android 8及以下(适用旧版本兼容的系统可以关注一下)
✅ 修复建议:
  • 尽量使用普通广播或 LocalBroadcastManager
  • 验证广播来源 (getPackage, getCallingUid)

📌 漏洞 ④:拒绝服务(DoS)

✅ 风险描述:

攻击者持续高频发送广播,触发广播内耗时操作导致卡顿甚至 ANR 崩溃。

☠️ Receiver 示例:
 @Override
 public void onReceive(Context context, Intent intent) {
     try {
         Thread.sleep(5000); // ⚠️耗时操作导致卡死
     } catch (InterruptedException e) {}
 }
⚙️ Manifest 配置:
 <receiver android:name=".SleepReceiver">
     <intent-filter>
         <action android:name="com.vuln.DOS"/>
     </intent-filter>
 </receiver>
💥 攻击命令:
 for i in $(seq 1 50); do
   adb shell am broadcast -a com.vuln.DOS;
 done
✅ 修复建议:
  • 广播中只做轻量操作,耗时处理转交 Service

📌 漏洞 ⑤:伪造广播触发发短信

☠️ 发短信接收器:
 public class SmsReceiver extends BroadcastReceiver {
     @Override
     public void onReceive(Context context, Intent intent) {
         String number = intent.getStringExtra("phone");
         String text = intent.getStringExtra("msg");
         SmsManager.getDefault().sendTextMessage(number, null, text, null, null);
     }
 }
⚙️ Manifest 无限制导出:
 <receiver android:name=".SmsReceiver">
     <intent-filter>
         <action android:name="com.vuln.SEND_SMS"/>
     </intent-filter>
 </receiver>
💥 利用命令:
 adb shell am broadcast -a com.vuln.SEND_SMS --es phone "13800000000" --es msg "你被黑了"
📌 特殊适用条件:
  • Android 11 以下系统(12+ 系统需显示声明 exported=true)
  • 无权限限制或 export=true

第三步:🔐 安全修复 + 最佳实践清单

风险类型修复建议
广播欺骗设置 android:exported="false",或加权限
信息泄露使用 sendBroadcast(intent,
"com.app.PRIVATE_PERMISSION")
广播劫持避免 sendOrderedBroadcast,或校验来源
拒绝服务耗时操作交由 Service,广播处理快速返回
动态注册泄露注册后及时 unregisterReceiver()

✅ Manifest 修复示例:

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

或:

 <receiver android:name=".SafeReceiver"
           android:permission="com.app.PRIVATE_PERMISSION">
     <intent-filter>
         <action android:name="com.vuln.SAFE_ACTION"/>
     </intent-filter>
 </receiver>

✅ 总结:三步完成 BroadcastReceiver 漏洞排查

  1. 识别接收器:找出所有 <receiver> 注册,查看是否暴露
  2. 逐个分析风险:是否执行敏感操作?是否加权限?是否验证 Intent?
  3. ADB 测试复现:主动发广播,看是否能触发预期外行为
© 版权声明
THE END
喜欢就支持一下吧
点赞15赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容