一、Android Service组件介绍
Android官网对Service组件的介绍如下,Service是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可通过绑定到服务与之进行交互,甚至是执行进程间通信(IPC)。例如,服务可在后台处理网络事务、播放音乐,执行文件I/O或与内容提供程序进行交互。
Service有三种类型,分别是前台服务,后台服务和绑定服务。其中,前台服务和后台服务分别执行用户能够注意和不能够直接注意到的操作;当使用绑定服务时,需要实现一组回调方法onStartCommand()(让组件启动服务)和onBind()(实现服务绑定),如下图所示,分别为两种方式创建服务的生命周期。
1-1
AIDL是Android Interface Definition Language,Android接口定义语言。若建立一个使用AIDL的IPC,需要经过以下流程:
服务端创建 aidl 文件,这里定义了接口的方法签名
Android SDK会根据创建的 .aidl 文件生成接口,接口中存在一个Stub的内部抽象类,用于拓展Binder类并实现AIDL接口定义的函数;除此以外,服务端还必须拓展Stub接口明确方法的具体实现。
新建Service并重写onBind(),返回Stub类的实现,从而给客户端调用。
客户端复制服务端的接口文件后,创建ServiceConnection就可以使用服务端提供的方法了。
这里举一个简单的例子。
1-2
如上图所示,创建AIDL文件后,利用build命令会生成Stub接口文件,如下图所示。
1-3
除此以外,还需要创建服务实现Stub接口,并在客户端使用
ServiceConnection连接Service。
1-4
1-5
Service组件作为提供APP服务的组件,经常需要被其他应用使用,而绝大多数问题也是由于其导出造成的,下面会例举几种的典型的攻击情况。
使用Drozer工具,能够找到导出的Service组件,如下所示,能够找到当前应用导出的组件以及所需的权限。
2-1
通过反编译APK,能够找到AndroidManifest.xml中有关Sertvice组件的配置。
在Android 12以下的版本,可以查找未显式声明android:exported属性并配置了intent-filter的Service组件,或者显式声明了android:exported="true"的Service组件;在Android 12中,使用了intent-filter的Service组件必须显式声明android:exported属性。通过反编译解析AndroidManifest.xml文件,我们可以看到是否存在导出的Service组件。
2-2
同其它Android组件一样,Service的拒绝服务主要是由于Service启动时对接收的Intent没有做异常情况处理,导致程序崩溃。比较典型的例子是Intent空指针异常和序列化对象类型转化异常。这里以一个短信发送的服务举例。
2-3
如上图所示,该服务能够发送短信,但是使用Intent接收数据时,未对数据的类型做出判断,我们对其发送序列化的数据。
2-4
发送之后可见应用异常关闭,报错如下所示。
2-5
当Service导出时,若调用时未对该Service进行权限管控或者对调用者未进行身份鉴别,那么恶意应用则可以构造恰当的参数调用该Service,导致恶意行为发生。
仍然以上述的短信服务为例,恶意应用可以利用该Service,在不申请短信权限(android.permission.SEND_SMS)的情况下发送短信,造成越权调用,如下图所示。
2-6
当恶意应用构造并发送如上Intent之后,我们可以在手机短信界面发现如下信息已经被发送。
2-7
除了这一类通过onStartCommand()方式创建的Service能够被外部调用,以bind()方式创建的未存在校验的Service同样能够被恶意应用调用,以上文中提到的AIDL连接为例,将生成的APK反编译,我们可以看到在该APK中只有编译好的Stub接口文件和相应的实现,并无原始的AIDL文件,如下所示。
2-8
2-9
针对上述的AIDL,我们可以新建一个测试应用,参照AIDL客户端建立连接的方式,生成相应的Stub接口文件并建立连接,如下所示。
2-10
2-11
上述的应用属于比较简单的业务代码,若.aidl文件中又依赖了其他的接口文件,且业务逻辑比较复杂时,就不适合用手动生成接口文件的方式建立连接了。我们可以采用dex2jar的方式将业务代码作为三方库引入自有应用,从而能够使用相应的接口函数,仍以上述的测试程序为例。
Dex2jar是Github上的一个开源项目,支持将APK文件,dex文件等转换成jar包,我们将目标APK转化成jar包,这里需要注意打包完成后,还需要删掉jar包内同Android本身库相关的文件,防止编译出错。
2-12
之后,将转化好的jar包放入app的libs目录下,并选择“Addas Library”,这样就成功引入了jar包,如下所示。
2-13
引入后,我们就不需要再手动建立AIDL文件了,并且能够达到与上述一样的执行效果。
除此以外,若接口函数较为复杂,我们也可以使用Stub接口提供的调用接口函数的方法,如下所示,具体情况还要根据具体业务情况来分析。
2-14
2-15
三、Android Service 防护小结
1、内部的Service组件显式设置exported为false。
2、公开的Service组件需对调用方进行校验,例如签名校验,权限校验等,签名校验需使用签名级别的protectionLevel来判断是否为可信应用调用。
3、对Intent接收到的内容进行校验,在Service的方法中也要对发送方的内容再次进行校验。
4、尽量不在Service数据传输中传递敏感数据。
参考文献:
https://mp.weixin.qq.com/s__biz=MzAwMjg1NTI2Nw==&mid=2650519945&idx=1&sn=b9d025511815009905019c6ef3519f45
[2] android Service漏洞挖掘 | tea9的博客
https://tea9.xyz/post/3182197634.html
https://developer.android.com/about/versions/12/behavior-changes-12?hl=zh-cn#exported
原文始发于微信公众号(vivo千镜):小白训练营|Android Service评估浅谈
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论