Android Broadcast Security(转)
原文地址:http://drops.wooyun.org/tips/4393
0x00 科普
Broadcast Recevier 广播接收器是一个专注于接收广播通知信息,并做出对应处理的组件。很多广播是源自于系统代码的──比如,通知时区改变、电池电量低、拍摄了一张照片或者用户改变了语言选项。应用程序也可以进行广播──比如说,通知其它应用程序一些数据下载完成并处于可用状态。 应用程序可以拥有任意数量的广播接收器以对所有它感兴趣的通知信息予以响应。所有的接收器均继承自BroadcastReceiver基类。 广播接收器没有用户界面。然而,它们可以启动一个activity来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。
0x01 知识要点
注册形式:动态or静态
元素的name属性指定了实现了这个activity的 Activity的子类。icon和label属性指向了包含展示给用户的此activity的图标和标签的资源文件。其它组件也以类似的方法声明── 元素用于声明服务, 元素用于声明广播接收器,而 元素用于声明内容提供器。 manifest文件中未进行声明的activity、服务以及内容提供器将不为系统所见,从而也就不会被运行。然而,广播接收器既可以在manifest文件中声明,也可以在代码中进行动态的创建,并以调用Context.registerReceiver()的方式注册至系统。
(静态与动态注册广播接收器区别)
回调方法
广播接收器只有一个回调方法:
1
|
void onReceive(Context curContext, Intent broadcastMsg) |
当广播消息抵达接收器时,Android调用它的onReceive() 方法并将包含消息的Intent对象传递给它。广播接收器仅在它执行这个方法时处于活跃状态。当onReceive()返回后,它即为失活状态。 拥有一个活跃状态的广播接收器的进程被保护起来而不会被杀死。但仅拥有失活状态组件的进程则会在其它进程需要它所占有的内存的时候随时被杀掉。 这种方式引出了一个问题:如果响应一个广播信息需要很长的一段时间,我们一般会将其纳入一个衍生的线程中去完成,而不是在主线程内完成它,从而保证用户交互过程的流畅。如果onReceive()衍生了一个线程并且返回,则包涵新线程在内的整个进程都被会判为失活状态(除非进程内的其它应用程序组件仍处于活跃状态),于是它就有可能被杀掉。这个问题的解决方法是令onReceive()启动一个新服务,并用其完成任务,于是系统就会知道进程中仍然在处理着工作。
权限
设置接收app
1
2
|
Intent setPackage(String packageName) (Usually optional) Set an explicit application package name that limits the components this Intent will resolve to. |
设置接收权限
1
2
|
abstract void sendBroadcast(Intent intent, String receiverPermission) Broadcast the given intent to all interested BroadcastReceivers, allowing an optional required permission to be enforced. |
protectionLevel
normal:默认值。低风险权限,只要申请了就可以使用,安装时不需要用户确认。
dangerous:像WRITE_SETTING和SEND_SMS等权限是有风险的,因为这些权限能够用来重新配置设备或者导致话费。使用此protectionLevel来标识用户可能关注的一些权限。Android将会在安装程序时,警示用户关于这些权限的需求,具体的行为可能依据Android版本或者所安装的移动设备而有所变化。
signature:这些权限仅授予那些和本程序应用了相同密钥来签名的程序。
signatureOrSystem:与signature类似,除了一点,系统中的程序也需要有资格来访问。这样允许定制Android系统应用也能获得权限,这种保护等级有助于集成系统编译过程。
广播类型
系统广播:像开机启动、接收到短信、电池电量低这类事件发生的时候系统都会发出特定的广播去通知应用,应用接收到广播后悔以某种形式再转告用户。
自定义广播:不同于系统广播事件,应用可以为自己的广播接收器自定义出一条广播事件。
Ordered Broadcast
OrderedBroadcast-有序广播,Broadcast-普通广播,他们的区别是有序广播发出后能够适配的广播接收者按照一定的权限顺序接收这个广播,并且前面的接收者可以对广播的内容进行修改,修改的结果被后面接收者接收,优先级高的接收者还可以结束这个广播,那么后面优先级低的接收者就接收不到这个广播了。而普通广播发出后,能够是适配的接收者没有一定顺序接收广播,也不能终止广播。
sticky broadcast
有这么一种broadcast,在发送并经过AMS(ActivityManagerService)分发给对应的receiver后,这个broadcast并不会被丢弃,而是保存在AMS中,当有新的需要动态注册的receiver请求AMS注册时,如果这个receiver能够接收这个broadcast,那么AMS会将在receiver注册成功之后,马上向receiver发送这个broadcast。这种broadcast我们称之为stickybroadcast。
sendStickyBroadcast()字面意思是发送粘性的广播,使用这个api需要权限android.Manifest.permission.BROADCAST_STICKY,粘性广播的特点是Intent会一直保留到广播事件结束,而这种广播也没有所谓的10秒限制,10秒限制是指普通的广播如果onReceive方法执行时间太长,超过10秒的时候系统会将这个广播置为可以干掉的candidate,一旦系统资源不够的时候,就会干掉这个广播而让它不执行。
(几种广播的特性)
变动
android3.1以及之后版本广播接收器不能在启动应用前注册。可以通过设置intent的flag为Intent.FLAG_INCLUDE_STOPPED_PACKAGES将广播发送给未启动应用的广播接收器。
关键方法
- sendBroadcast(intent)
- sendOrderedBroadcast(intent, null, mResultReceiver, null, 0, null, null)
- onReceive(Context context, Intent intent)
- getResultData()
- abortBroadcast()
- registerReceiver()
- unregisterReceiver()
- LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- sendStickyBroadcast(intent)
0x02 分类
- 私有广播接收器:只接收app自身发出的广播
- 公共广播接收器:能接收所有app发出的广播
- 内部广播接收器:只接收内部app发出的广播
安全建议
intent-filter节点与exported属性设置组合建议
私有广播接收器设置exported='false',并且不配置intent-filter。(私有广播接收器依然能接收到同UID的广播)
<receiver android:name=".PrivateReceiver" android:exported="false" />
对接收来的广播进行验证
内部app之间的广播使用protectionLevel='signature'验证其是否真是内部app
- 返回结果时需注意接收app是否会泄露信息
发送的广播包含敏感信息时需指定广播接收器,使用显示意图或者
setPackage(String packageName)
sticky broadcast粘性广播中不应包含敏感信息
Ordered Broadcast建议设置接收权限receiverPermission,避免恶意应用设置高优先级抢收此广播后并执行abortBroadcast()方法。
0x03 测试方法
1、查找动态广播接收器:反编译后检索registerReceiver(),
dz> run app.broadcast.info -a android -i
2、查找静态广播接收器:反编译后查看配置文件查找广播接收器组件,注意exported属性
3、查找发送广播内的信息检索sendBroadcast与sendOrderedBroadcast,注意setPackage方法于receiverPermission变量。
发送测试广播
1
2
3
4
5
6
7
8
9
10
11
12
|
adb shell: am broadcast -a MyBroadcast -n com.isi.vul_broadcastreceiver/.MyBroadCastReceiver am broadcast -a MyBroadcast -n com.isi.vul_broadcastreceiver/.MyBroadCastReceiver –es number 5556 . drozer: dz> run app.broadcast.send --component com. package .name --action android.intent.action.XXX code: Intent i = new Intent(); ComponentName componetName = new ComponentName(packagename, componet); i.setComponent(componetName); sendBroadcast(i); |
接收指定广播
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class Receiver extends BroadcastReceiver { private final String ACCOUNT_NAME = "account_name" ; private final String ACCOUNT_PWD = "account_password" ; private final String ACCOUNT_TYPE = "account_type" ; private void doLog(Context paramContext, Intent paramIntent) { String name; String password; String type; do { name = paramIntent.getExtras().getString(ACCOUNT_NAME); password = paramIntent.getExtras().getString(ACCOUNT_PWD); type = paramIntent.getExtras().getString(ACCOUNT_TYPE); } while ((TextUtils.isEmpty(name)) || (TextUtils.isEmpty(password)) || (TextUtils.isEmpty(type)) || ((!type.equals( "email" )) && (!type.equals( "cellphone" )))); Log.i( "name" , name); Log.i( "password" , password); Log.i( "type" , type); } public void onReceive(Context paramContext, Intent paramIntent) { if (TextUtils.equals(paramIntent.getAction(), "account" )) doLog(paramContext, paramIntent); } } |
0x04 案例
案例1:伪造消息代码执行
WooYun: 百度云盘手机版钓鱼、信息泄露和代码执行高危漏洞三合一
案例2:拒绝服务
尝试向广播接收器发送不完整的intent比如空action或者空extra。
- WooYun: 乐phone手机系统重启漏洞
- WooYun: QQ手机管家拒绝服务漏洞
- WooYun: 手机百度4.5.1Android客户端DOS攻击
- WooYun: 百度某手机应用拒绝服务漏洞
- WooYun: 搜狗输入法安卓客户端本地拒绝服务漏洞
- WooYun: 百度云盘客户端拒绝服务
- WooYun: su提权广播劫持导致拒绝服务攻击 (上面都是伪造,这个是劫持)
案例3:敏感信息泄漏
某应用利用广播传输用户账号密码
隐式意图发送敏感信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class ServerService extends Service { // ... private void d() { // ... Intent v1 = new Intent(); v1.setAction( "com.sample.action.server_running" ); v1.putExtra( "local_ip" , v0.h); 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); } } this .sendBroadcast(v1); } |
接收POC
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class BcReceiv extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent){ String s = null ; if (intent.getAction().equals( "com.sample.action.server_running" )){ String pwd = intent.getStringExtra( "connected" ); s = "Airdroid => [" + pwd + "]/" + intent.getExtras(); } Toast.makeText(context, String.format( "%s Received" , s), Toast.LENGTH_SHORT).show(); } } |
修复后代码,使用 LocalBroadcastManager.sendBroadcast() 发出的广播只能被app自身广播接收器接收。
1
2
3
|
Intent intent = new Intent( "my-sensitive-event" ); intent.putExtra( "event" , "this is a test event" ); LocalBroadcastManager.getInstance( this ).sendBroadcast(intent); |
案例4:权限绕过
- WooYun: 小米MIUI漏洞可能导致硬件资源消耗
- WooYun: 无须权限随意开启和关闭手机wifi功能
- WooYun: 华为荣耀3X Android4.2提权打电话漏洞
- WooYun: 酷派最安全手机s6拨打电话权限绕过
- WooYun: 酷派最安全手机s6程序锁绕过
0x05 参考
http://www.jssec.org/dl/android_securecoding_en.pdf
Android Broadcast Security(转)的更多相关文章
- android Broadcast介绍
在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制.而BroadcastReceiver是对发送出来的Broadcast进行过滤接受并响应的一类组件.发送Broadca ...
- Android Broadcast Receiver 使用入门
Broadcast Receiver 的使用 1.Broadcast Receiver简介 2.Broadcast Receiver接收系统自带的广播 3.自 ...
- Android Broadcast Receiver注册
之前有关 Broadcast Receiver的链 动态注册 1.我们新建一个广播接受类,我们创建一个内部类让他继承BroadcastReceiver,并且重新其中当有广播来到时执行的方法onRece ...
- Android app security安全问题总结
数据泄漏 本地文件敏感数据不能明文保存,不能伪加密(Base64,自定义算法等) android:allowbackup=false. 防止 adb backup 导出数据 Activity inte ...
- Android——Broadcast Receive 相关知识总结贴
Android系统中的广播(Broadcast)机制简要介绍和学习计划 http://www.apkbus.com/android-99858-1-1.html android----BroadCas ...
- Android -- Broadcast接收
Broadcast是Android四大组件之一,是一种广泛运用的在应用程序之间传输信息的机制.最经典的举例是: “我们拿广播电台来做个比方.我们平常使用收音机收音是这样的:许许多多不同的广播电台通过特 ...
- Android Activtity Security(转)
Android四大组件之一--Activity安全详解. 原帖地址:http://drops.wooyun.org/tips/3936 0x00 科普 Android每一个Application都是由 ...
- android Broadcast 总结
1, 生命周期 在android官方文档中,推荐我们在onResume中进行 registerReceiver, 在onPause中进行unRegisterReceiver. 他们给出的理由是: If ...
- Android Broadcast Receive
Broadcast Receive 广播接收(Broadcast Receive)为android的四大组件之一.主要用于监听广播消息,并做出响应.与应用程序中监听事件相比而言,该监听事件为全局监听. ...
随机推荐
- 网络设备之分配net_device结构
注册网络设备时,会调用pci_driver->probe函数,以e100为例,最终会调用alloc_netdev_mqs来分配内存,并且在分配内存后调用setup函数(以太网为ether_set ...
- ThinkPHP5 正则验证中有“|”时提示“规则错误”的解决方案
正则规则中有“|”时,会引起解析错误: 'regex:\d{3,4}[\s,-]?\d{7,8}|1[3,4,5,8]\d[\s,-]?\d{4}[\s,-]?\d{4}' 使用数组语法可以解决: [ ...
- CentOS在ssh下远程重装系统
CentOS在ssh下远程重装系统 http://www.zxsdw.com/index.php/archives/913/ 国外VPS服务器一般都有控制面板,有很多种系统可自行安装,但国内有些IDC ...
- 【学习笔记】动态树Link-Cut-Tree
这是两个月前写的,看能不能搬运过来…… 动态树是一类维护森林连通性的问题(已纠正,感谢ZQC巨佬),目前最(wo)常(zhi)见(hui)的动态树就是LCT(Link-Cut-Tree),然而LCT似 ...
- 辨别苹果数据线真伪 苹果计算器 Dashboard 知识
辨别苹果数据线真伪 苹果计算器 Dashboard 知识 苹果数据线真伪的最简单的辨别: 线质柔软 用数据线连接适配器(苹果自带的适配器)充电 连接手机 如果该手机数据线是假的, 在手机上会提示”该 ...
- freemark学习
学习地址: http://blog.csdn.net/hejinxu/article/details/6694890 对freemarker的用法与语法进行了详细的讲解 http://freema ...
- Redis在CentOS 7上的安装部署
简介: Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服务器端计算集合的并,交和补集( ...
- [ python ] 反射及item系列
反射 什么是反射? 通过字符串的形式操作对象相关属性.python中的事物都是对象: 关键方法: (1)getattr:获取属性 (2)setattr:设置属性 (3)hashattr:检测是否含有属 ...
- linux命令(42):wc命令
Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 1.命令格式: wc [选项]文件... 2.命令功能: 统计指定文件中的字节数. ...
- [转] Socket心跳包异常检测的C语言实现,服务器与客户端代码案例
转载自:zxh2075的专栏 在Socket心跳机制中,心跳包可以由服务器发送给客户端,也可以由客户端发送给服务器,不过比较起来,前者开销可能较大.本文实现的是由客户端给服务器发送心跳包,服务器不必返 ...