🚨Android 广播劫持完全解析:一招看穿你的 App 有没有被“广播间谍”监听!
本文为你讲清楚:什么是广播劫持、哪些写法容易出问题、攻击者是如何“插队”成功的、开发者如何防止广播泄露和被操控。
🧭 文章导图
- 什么是 BroadcastReceiver 和广播机制?
- 什么是“有序广播”?为什么它容易出问题?
- 广播劫持的真实攻击方式详解(代码+攻击流程)
- 哪些写法会造成劫持风险?
- 如何修复和防御?
- 小白也能看懂的排查技巧
1️⃣ 什么是 BroadcastReceiver 和广播机制?
Android 中的广播(Broadcast)机制允许 App 之间或 App 内部通过广播消息进行通信。
🔧 常见用法:
- 网络变化通知
- 电池电量变化
- 用户登录成功通知
- 支付完成通知等
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String msg = intent.getStringExtra("msg");
Log.d("Receiver", "收到广播:" + msg);
}
}
2️⃣ 什么是“有序广播”?为什么它容易出问题?
✅ 普通广播:sendBroadcast()
一次性同时发给所有匹配的广播接收器,不可以中断、没有先后顺序。
⚠️ 有序广播:sendOrderedBroadcast()
按照注册优先级(
priority
)一个一个地传递,谁优先级高,谁先接收,并且:
- 可以调用
abortBroadcast()
阻断广播; - 可以调用
setResultData()
修改广播结果。
🧨 这就意味着:如果攻击者写了一个优先级高的广播接收器,就能拦截你 App 的广播,甚至阻止你自己的组件接收。
3️⃣ 广播劫持攻击者如何下手?
🎯 攻击者思路:
“只要你用的是有序广播,而且没有加权限或指定包名,那我写一个 App 注册高优先级 Receiver,就可以抢在你自己的 Receiver 前收到广播,并阻止你继续接收。”
🦠 攻击者 App 示例代码:
AndroidManifest.xml 注册高优先级接收器:
<receiver android:name=".HijackReceiver">
<intent-filter android:priority="1000"> <!-- 优先级越高越早收到 -->
<action android:name="com.victim.LOGIN_BROADCAST" />
</intent-filter>
</receiver>
HijackReceiver.java(攻击者逻辑):
public class HijackReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.e("Hijack", "广播被劫持!");
abortBroadcast(); // 🚫 阻止后续接收器继续接收
setResultData("我劫持了广播");
}
}
💥 被劫持后可能发生的后果:
- App 内逻辑无法收到广播(功能失效)
- 广播中数据被修改(如登录状态、验证码)
- 敏感数据被提前拿到(如 token、短信)
4️⃣ 哪些写法容易导致被劫持?
❌ 典型不安全写法:
Intent i = new Intent("com.victim.LOGIN_BROADCAST");
i.putExtra("token", "abc123");
sendOrderedBroadcast(i); // ❌ 没有权限限制、没指定接收范围
✅ 安全写法推荐:
Intent i = new Intent("com.victim.LOGIN_BROADCAST");
i.setPackage("com.victim.app"); // 限定接收者包名
sendOrderedBroadcast(i, "com.victim.PRIVATE_PERMISSION"); // 限制权限
5️⃣ 如何防止广播被劫持?
防御手段 | 示例 | 作用 |
---|---|---|
✅ 限制广播接收权限 | sendOrderedBroadcast(intent, "com.xxx.PERMISSION") | 恶意 App 注册不到 |
✅ 限定接收者 | intent.setPackage("com.xxx") | 只有指定 App 可接收 |
✅ 检查广播来源 | intent.getPackage() / getCallingPackage() | 防止伪造广播 |
❌ 避免使用sendOrderedBroadcast | 改用 sendBroadcast() 或 LocalBroadcastManager | 没有优先级劫持问题 |
✅ AndroidManifest 中设置 exported="false" (Android 12+) | <receiver android:exported="false"/> | 防止被其他 App 调用 |
6️⃣ 小白排查指南:三步查广播劫持风险
✅ 第一步:全局搜索可疑写法
关键词:
sendOrderedBroadcast
setResultData
abortBroadcast
🔍 目的:找出发广播/处理广播的地方是否加权限或限制
✅ 第二步:检查 Manifest 和动态注册
关键词:
<receiver
intent-filter
registerReceiver
- 是否注册了暴露给外部的 Receiver?
- 是否指定了权限(
android:permission
)? - 是否设置
exported="false"
?
✅ 第三步:尝试 ADB 模拟广播测试(只用于辅助验证)
adb shell am broadcast -a com.victim.LOGIN_BROADCAST --es token "fake_token"
如果这个命令能触发 App 的逻辑说明广播是公开的,具备被劫持条件。
🧨 真实开发常见失误案例
场景 | 错误做法 | 后果 |
---|---|---|
登录成功发广播 | 没加权限 | 恶意 App 抢到 token |
支付结果广播 | 广播未设限制 | 被劫持篡改交易结果 |
验证码接收广播 | 监听器未限制 | 被他人 App 提前读取验证码 |
✅ 最终总结
有效范围适用于Android9以下
- 🧠 有序广播是一种按优先级分发的广播形式,容易被高优先级 App 插手;
- 🦠 攻击者无需任何特权,只需写 App 注册高优先级 Receiver;
- 🛡️ 防护关键在于:权限保护 + 指定接收包名 + 避免使用有序广播。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容