0x00 BroadcastReceiver简介
1、漏洞场景
-
广播即intent;
-
当发送一个广播时,系统会将发送得到广播与系统中已注册的符合条件的接收者的
intent-filter
进行匹配,若匹配成功,则执行相应接收者的onReceive
函数; -
发送广播时如果处理不当,恶意app便可以嗅探、拦截广播,致使敏感数据泄露;
-
接收广播时处理不当则可以导致拒绝服务、消息伪造、越权操作。
2、漏洞分类
- 信息泄露
- 消息伪造
- 权限绕过
- 拒绝服务
0x01 敏感信息泄露
1、漏洞原理
发送的intent没有明确指定接收者,只是简单匹配Action。恶意app可以通过注册广播接收者嗅探拦截到这个广播,该广播的敏感信息将被窃取。
2、漏洞示例
隐式intent发送敏感信息:
private void d() {
Intent v1 = new Intent();//隐私intent
v1.setAction("com.sample.action.server_running");//设置action
v1.putExtra("local_ip",v0.h);//设置key-value
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")){
//action匹配
String pwd = intent.getStringExtra("connected");
s="Airdroid => ["+pwd+"]/"+intent.getExtras();
}
Toast.makeTest(context,String.format("%sReceived",s),Toast.LENGTH_SHORT).show();
}
3、修复代码
使用LocalBroadcastManager.sendBroadcast
发出的广播只能被app自身广播接收器接收。
Intent intent = new Intent("my-sensitive-event");
intent.putExtra("event","this is a test event");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
0x02 消息伪造
1、漏洞原理
暴露的Receiver对外接收Intent,如果攻击者构造恶意的消息放在Intent中传输,被调用的Receiver接收有可能产生安全隐患。
2、漏洞示例
比如构造短信发送内容给广播接收器:
public class SendSMSNowReceiver extends BroadcastReceiver {
Context context;
@Override // android.content.BroadcastReceiver
public void onReceive(Context arg8, Intent arg9) {
this.context = arg8;
SmsManager sms = SmsManager.getDefault();
Bundle bundle = arg9.getExtras();
sms.sendTextMessage(bundle.getString("phoneNumber"), null,bundle.getString("message"), null, null);
Utils.makeToast(this.context, "Your text message has been sent!", 1);
}
}
3、修复代码
设置该组件注册时,声明ProtectionLevel为Signature
验证。
android:protectionLevel="signature"
0x03 权限绕过*
1、漏洞原理
- 广播接收器的两种注册方式
- 静态注册:在Manifest.xml文件中通过
<reciver>
标签静态注册。 - 动态注册:通过
Context.registerReceiver()
动态注册,指定相应的intentFilter
参数。
- 静态注册:在Manifest.xml文件中通过
动态注册的广播接收器是默认导出的,如果没有做权限限制,导致接收器可以接收一个外部可控的url或其他命令,导致越权利用某些功能。
2、防护
建议使用LocalBroadcastManager
类,相较于Context.sendBroadcast(intent)
有优势。
0x04 拒绝服务
1、漏洞原理
暴露的BroadcastReceiver没有设置相应的权限保护,很容易受到拒绝服务攻击。通过传递恶意畸形的intent数据给广播接收器,广播接收器无法处理异常导致crash。
2、防护
谨慎处理接收的intent以及其携带的信息。
对接收的任何数据做try catch
处理,对不符合预期的信息做异常处理。
常见异常处理:
- 空指针异常处理
- 类型转换异常(序列化)
- 数组越界访问异常
- 类未定义异常
- 其他异常
0x05 测试方法
1、查找动态广播接收器
反编译后查找registerReceiver()
2、查找静态广播接收器
反编译后查看配置文件查找广播接收器组件,注意exported
属性。
3、查找发送广播内的信息
检索sendBroadcast
和sendOrderedBroadcast
,注意setPackage
方法和receivePermission
变量。
0x06 安全建议
关键:intent-filter设置、exported属性设置
-
私有广播接收器:设置
exported=‘false’
,并且不配置intent-filter
。 -
粘性广播:不应包含敏感信息。
-
有序广播:设置接收权限
receivePermission
,避免恶意应用设置高优先级抢收此广播后并执行abortBroadcast()
方法。 -
发送的广播包含敏感信息时需指定广播接收器,使用
显示意图
或者setPackage(String packageName)
-
内部app之间的广播使用
protectionLevel='signature'
验证其是否真是内部app -
对接收来的广播进行验证,返回结果时需注意接收app是否会泄露信息。
0x07 参考
https://xuanxuanblingbling.github.io/ctf/android/2018/02/12/Android_app_part1/