论文IntentFuzzer: Detecting Capability Leaks of Android Applications阅读笔记
IntentFuzzer: Detecting Capability Leaks of Android Applications
目标是检测Android上的权限泄露问题,比如组件C具有权限P,另一个应用A可能通过构造特定的intent来调用组件C,从而达到使用权限P的目标。
一个典型的场景就是C有权限P且exported=true,但是在响应intent的时候没有鉴别是不是外来的,导致泄露的权限P。文章使用了若干启发式搜索方法来构造intent,同时修改system代码检测部分API并生成反馈,形成了一种基于的反馈引导的fuzz方法。
1 Intro
回顾了之前的方法,介绍了Android的权限泄露问题(Capibility Leak):
Capability leak is such a vulnerability that an application exposes some permissions, by which other applications without these permissions can access protected resource.
2 Background
2.1 Permission Model
Google的设计规则:App默认情况下不能获取危险的权限,手机用户需要在应用安装的时候授予权限。
2.2 Inter Component Communication
ICC就是指intent机制嘛。
还有就是androidmanifest.xml中可以设置activity、service为exported=false来使得这个activity拒绝响应app之外的intent,未设置时默认是true。
这篇文章主要关注这些exported=true,可以响应外来intent的组件。
2.3 Capability Leaks
Capability Leak, 也称 Permission Re-Delegation
一个例子:正常应用A有权限P,A有一个对外暴露(exported=true)的组件C,而且C没有做好intent的安全检查,那么恶意应用M可能在无授权的情况下向C发送构造的intent从而使用P权限。
其实这里只要C简单的判断一下intent的发送者是不是App自身的组件就可以避免权限泄露了,但是广大的开发者不以为意。
3 System Design
本研究动态地生成合适的intent并发送到目标组件,然后检查是否有权限泄露。
对于intent的生成,会从manifest中提取信息构建基本框架,然后通过修改system的API函数来进行反馈,修正intent的具体字段。
3.1 Fuzz Strategy
进行了一系列的讨论,把研究目标缩小到Started Service、Broadcast Receiver和explicit intent:
- 作者认为Activity虽然也有提权攻击和页面欺诈钓鱼的情况,但是因为activity一般带界面且直接与用户交互,遇到问题时用户自己可以关掉activity来终止代码的运行,所以并不是非常严重。(存疑)
- 作者把service分为started service和bound service两种,其中bound service不接受外来intent,所以不考虑。
- 作者把intent分为explicit intent和implicit intent两种(显式和隐式),会使用显式intent来fuzz。
- 作者把capability leak分为两种,一种是组件有意对外exported但是没有合理地检查intent的发送方权限;另一种是组件疏忽对外暴露。这两种情况下,组件都会接收显式intent。
3.2 Permission Leak Detection
前面说到未授权M通过带授权A的组件C执行了权限P,如何确定P权限被执行了?
IntentFuzzer会在设备上植入一个不申请任何权限的Agent,然后修改Android系统代码,实时检查权限P是否被申请。(权限在app安装的时候授予,但是在运行时会即时进行permission check)
3.3 Intent Construction
对于前面提到的Started Services,其入口函数onStart-Command(),对于Broadcast Receiver,其入口函数是onReceive()。
对于intent涉及到的相关结构,其构造方法如下:
Action:
对于那些有意exported来接收外来显式intent的组件,它们会在manifest中通过intent-filter来定义可以响应的action类型,枚举这些预定的action来测试对应组件即可;
对于那些疏忽exported意外地可以接受外来显式intent的组件,它们本身并不会在manifest中定义intent-filter,因为它们本来应该只响应app内部intent的。它们可能会检查action的值,然后决定运行后续的代码,如下面的代码示例。对于这些action的值,Google本身预定义并推荐使用了一系列的值,当然app本身可以定义自己的值,不过它们往往会是packagePath.ActioType
的模式,所以本研究会从dex的变量池中选出符合这种模式的字符串加上Google预定义的值,作为可能的action键值。1
2
3
4
5
6
7public void onReceive(Context context, Intent intent) {
SmsManager smsManager = SmsManager.getDefault();
String action = "com.example.test.action.SEND_SMS";
if (action.equals(intent.getAction())) {
smsManager.sendTextMessage("10086", null, "test",null, null);
}
}Data:
可以从intent-filter关于data属性的定义推测data的类型,具体可以从scheme://host:port/path
这个模式来推测。研究中预先准备了一些data,如果有合适的intent-filter,就会使用对应的data来进行测试。Extras:
Extras就是一系列包含Java原语的键值对,并不在intent-filter中定义,但是会在目标组件的代码中反应出来。
如下面示例代码,可以通过提取getStringExtra(‘name’)这样的API来判断目标组件会从intent中提取哪些extra。
具体来说,IntentFuzzer又一次修改的系统源码中关于getXXXExtra()这里函数,通过log返回它的调用情况。
在一次测试中,如果目标组件尝试从intent中提取类型为String键名为sms的extra数据但是没有成功,那么log中会包含相关的feedback,告诉intentfuzzer在下一次测试中,为测试intent加上这样的extra数据。
这样一来会测试到更为深层的代码逻辑。1
2
3
4
5
6
7
8public int onStartCommand(Intent intent, int flags, int startId) {
SmsManager smsManager = SmsManager.getDefault();
String smsContent = intent.getStringExtra("sms");
if (smsContent != null && smsContent != "") {
smsManager.sendTextMessage("10086", null, smsContent, null, null);
}
...
}Category:
显式intent一般不考虑category,相关匹配机制参考:https://blog.csdn.net/iispring/article/details/48481793Flags:
flags会指示系统如何运行目标组件,不需要考虑。
3.4 General Fuzzing Steps
对于exported组件:
- 枚举每个intent-filter中的Action,循环2-5
- 如果intent-filter有Data,才构建Data数组
- 初始化Extra键值对集合为空集E
- 构造并发送一个包含Action,Data,E-extra的intent
- 等待几秒,看看是否触发了permissionCheck和getXXXExtra的API。如果获取了一个新的Extra数据,向E中添加这样的键值对,回到4,否则退出当前循环。
对于没有intent-filter的组件,也即那些可能因为没有设置而被默认暴露的组件:
- 构建隐含Action(即常量池+预设值),对于每一个隐含Action,执行2-4
- 初始化Extra为空集E
- 构造并发送一个包含Action,E-extra的intent
- 等待几秒,看看是否触发了permissionCheck和getXXXExtra的API。如果获取了一个新的Extra数据,向E中添加这样的键值对,回到3,否则退出当前循环。
4 Implementation
4.1 Architecture
在drozer的框架上构建的,并且编写的drozer module来实现IntentFuzzer console。
4.2 System Modification
拦截checkPermission(String permision, int pid, int uid)
函数,向logcat中输出permission和uid就知道当前是那个应用在使用什么权限。
拦截getXXXExtra(String name, ...)
这一类函数,就指导当前应用的组件在尝试从intent中获取那些extra数据。
5 Evaluation
5.1 Experiment Design
2183 Google Play Apps, SAMSUNG Galaxy Nexus, Android 4.2.2
closed-source ROMs in Redmi Android4.2.2 & Lenovo K860i 4.2.1
5.2 Case Study
有一些实际的case分析,增加了文章的可信度。