文章目录
- 前言
- 框架安装
- PC控制端
- 手机代理端
- 连接测试
- 实战测试
- Activity越权
- 内容提供器
- 敏感数据读取
- SQL注入测试
- 任意文件读取
- Service提权
- 广播接收器
- 发送恶意广播
- 拒绝服务攻击
- 总结
前言
Drozer 是 MWR Labs 开发的一款 Android 安全测试框架,是目前最好的 Android 安全测试工具之一。其官方文档说道:“Drozer允许你以一个普通android应用的身份与其他应用和操作系统交互”。Drozer是一种交互式的安全测试工具,使用Drozer进行安全测试时,用户在自己的工作站上输入命令,Drozer会将命令发送到Android设备上的代理程序执行。
实际上 Drozer 的核心功能就是通过分析 AndroidManifest.xml,看四大组件中有没有可 export 的,如果有那么就进一步检测这些可导出的组件是不是存在相应的安全问题。
Android 系统的组件共有四种,其主要用途分别为:
组件 | 用途 |
Activity | 呈现可供用户交互的界面,是最常见的组件 |
Service | 长时间执行后台作业,常见于监控类应用 |
Content Provider | 在多个APP间共享数据,比如通讯录 |
Broadcast Receiver | 注册特定事件,并在其发生时被激活 |
1、什么是组件导出?
简而言之,就是别的APP也可以访问这个组件。再总而言之,就是组件权限的控制。
2、组件导出有什么用?
有些APP的功能需要提供一些接口给其它APP访问,就需要把相关的接口功能放在一个导出的组件上。
3、组件导出有什么危害?
因为权限声明是以组件为单位的,A组件调用B组件的功能来访问操作系统API时,适用于B组件的权限声明。如果B作为导出组件,没有进行严格的访问控制,那么A就可以通过调用B来访问原本没有声明权限的功能,构成本地权限提升。
框架安装
PC控制端
相关环境要求:
- Drozer使用 Python 2.7 编写不支持 Python 3.x,所以 PC 端需要装 Pthon 2.7环境;
- JDK 环境 和 ADB(Android Debug Bridge),一般在Android SDK安装目录下的 platform-tools 文件夹下就有,也可以另外下载安装;
- 需要安装Python其他库:
pip install protobuf pyOpenSSL Twisted service_identity
(不安装的话与客户端连接会报错)。
此处 PC 端选择了 Windows 10,故从官网下载 drozer-2.4.4.win32.msi 安装程序,安装过程中注意需要选择 Python 2.7 的本地路径:
安装成功后在 Python 2.7 的安装路径下可以找到 Drozer:
至此,Drozer 的PC端环境准备结束。
手机代理端
在官网下载 Drozer 的 APK 客户端程序 drozer-agent-2.3.4.apk,可以安装在实体手机(使用USB连接PC)也可以安装在模拟器,下面选择 Genymotion 模拟器:
手机模拟器安装完 Drozer Agent 后打开 APP ,点击右下角的按钮开启服务:
【补充】利用 ADB 还可以获得模拟器的 Shell(更多ADB命令操作自行百度):
连接测试
PC控制端和手机客户端程序都准备好以后,开始进行连接测试:
1、切换到 drozer 安装目录,运行 cmder:
2、命令行执行adb forward tcp:31415 tcp:31415
,作用是将PC端 31415 端口的数据转发到手机端 31415 端口,从而实现PC和手机的通信:
3、命令行执行 drozer console connect
用于连接手机端的agent(记得手机代理端得开启服务,执行该命令后自动连接手机31415端口),成功后会有如下图所示界面:
4、执行命令list,可以查看Drozer当前可用的所有模块:
5、比如执行命令run app.package.list
,可列出模拟器设备中所有已经安装的App包列表:
6、执行命令run app.package.info -a 包名
,可列出应用程序的基本信息,包括APP的版本、数据存储路径、安装路径、相关权限等:
实战测试
Drozer 官网提供了一个用于漏洞测试的 Demo apk 程序 sieve.apk,下载下来安装到手机(USB连接实体测试机到PC):
APP第一次打开后主页面如下,要求设置访问密码:
运行 Drozer 并执行命令run app.package.list -f sieve
,利用关键词 “sieve” 进行手机上包名的搜索得出具体包名:
执行命令run app.package.info -a com.mwr.example.sieve
,获取 sieve 应用的版本、数据存储目录、用户ID、权限等基本信息:
执行命令 run app.package.attacksurface 包名
,识别出应用的攻击面(Drozer会告诉我们应用是否有 export 可导出得暴露的组件):
Activity越权
Activity是Android组件中最基本也是最为常见用的四大组件之一,是一个负责与用户交互的组件。
APP应用中主活动(比如MainLoginActivity)是app启动时的主界面,必须可以导出,但其他 Activity 正常情况下是不能导出的,遇到可导出且不需要权限的 Activity活动组件,可以用 Drozer 命令来尝试直接启动该活动,往往可以发现越权访问(如绕过登录验证访问数据)的漏洞。
在 Drozer 中继续执行命令run app.activity.info -a com.mwr.example.sieve
,可查看 sieve APP对外的 activity 组件信息:
APP首次运行设置完密码后运行便要求输入密码(对应活动com.mwr.example.sieve.MainLoginActivity):
验证成功后进入下一级活动(com.mwr.example.sieve.PWList)查看密码:
从上面探测的信息发现调用以上可导出的对外 Activity 都不需要任何权限,那么我们可以使用 Drozer (执行命令run app.activity.start --component 包名 活动组件名
)直接调用查看密码的 Activity ,从而实现绕过登录验证功能,越权查看密码:
至此,成功借助 Drozer 绕过登录授权验证,造成 Activity组件的越权访问漏洞。
内容提供器
Content Provider为存储和获取数据提供统一的接口。可以在不同的应用程序之间共享数据。Content Provider组件中存在以下常见的漏洞:
- 读写权限漏洞Content Provider中通常都含有大量有价值的信息,比如用的电话号码或者社交帐号登录口令,而确认一个content provider是否有能被攻击的漏洞的最好的办法,就是尝试攻击它一下。可以用drozer来寻找一些不需要权限的
contentprovider:dz> runapp.provider.info –permission null
这条命令能列出所有不需要任何读写权限的Content Provider,然后找到相对应的包,去访问给定包存放在它的Content Provider中的数据。如果一些 Content Provider 的 URI 不需要读权限,那就可以通过drozer工具提取其中的数据。在某些情况下,设置和执行读写权限不当,也会将ContentProvider中的数据暴露给攻击者。除了提取数据,对于写权限管理不当的Content Provider还可以向其中写入数据,使得攻击者可以将恶意数据插入到数据库中。 - Content Provider中的SQL注入漏洞和Web漏洞类似,安卓APP也要使用数据库,那就也有可能存在SQL注入漏洞。主要有两类,第一类是SQL语句中的查询条件子语句是可注入的,第二类是投影操作子句是可注入的。使用drozer可以很容易的找出查询条件子句可注入的content provider。
dz> runapp.provider.query [URI] –selection “1=1”
也可以使用其他恒为真的值,例如“1-1=0”,“0=0”等等。如果APP存在SQL注入漏洞,那么输入这行指令后就会返回数据库中的整张表。 - Provider文件目录遍历漏洞当Provider被导出且覆写了openFile方法时,没有对Content Query Uri进行有效判断或过滤。攻击者可以利用openFile()接口进行文件目录遍历以达到访问任意可读文件的目的。
在 Drozer 中执行命令run app.provider.info -a com.mwr.example.sieve
可以获取 Content Providers 的详细信息:
从返回结果可以看出,对 sieve 应用的 DBContentProvider 内容提供器的访问除了/Keys 路径,其他的都不需要权限;而对 FileBackupProvider 内容提供器的访问则不需要任何权限,那么我们就可以从中获取敏感数据。
Drozer 提供了一个模块,可以帮助我们获取内容提供器的 URIS 资源访问路径,执行命令 run scanner.provider.finduris -a com.mwr.example.sieve
(-a 指定了应用名称,不加参数会扫描手机安装的所有app):
可以看到我们有三个URI 可以访问,考虑 /Keys 需要权限,所以我们可以使用content://com.mwr.example.sieve.DBContentProvider/Passwords/
来测试。
敏感数据读取
执行命令 run app.provider.query uri
,可从不需要权限的内容提供器中读取敏感数据:
SQL注入测试
由于andorid应用大多使用sqlite数据库存储数据,既然这些数据库使用sql,那么就有可能存在sql注入漏洞。下面我们将通过简单的方法测试是否存在该漏洞。
1、首先执行以下命令:
run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "'"
可以看到返回了错误信息,爆出了注入点,我们就可以构造sql从而获取敏感信息:
2、下面是另外一个注入点:
run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --selection "'"
从两个返回结果看,在 column 和 where 处都存在注入点:
3、类似于sqlmap,借助 Drozer 还可以进一步查看都有哪些表,并且可以查询表中的数据。
首先查询存在哪些表:
run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "* FROM SQLITE_MASTER WHERE type='table';--"
结果如下图所示:
接着查询表中的数据:
run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "* FROM Key;--"
结果如下图所示:
4、最后,我们也可以使用扫描功能对该app注入点位置进行自动扫描(执行命令run scanner.provider.injection -a com.mwr.example.sieve
):
任意文件读取
执行以下命令可对底层文件进行读取:
执行以下命令可进行目录遍历漏洞检测:
Service提权
作为Android中四大组件之一,拥有重要的地位,Service具有和Activity一样的级别,只是没有界面,是运行于后台的服务。其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个service与之交互(IPC机制),例如,一个service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。从表面上看service并不具备危害性,但实际上service可以在后台执行一些敏感的操作。
Service存在的安全漏洞包括:权限提升,拒绝服务攻击。没有声明任何权限的应用即可在没有任何提示的情况下启动该服务,完成该服务所作操作,对系统安全性产生极大影响。
以下示例如何借助可导出的Service组件进行权限提升,演示过程基于另一个漏洞Demo APP,下载地址:OWASP GoatDroid- FourGoats Android App.apk,安装后主页面如下:
使用 jadx-gui 反编译 APK 文件并查看源码:
发现 org.owasp.fourgoats.goatdroid.LocationService 服务可被导出且不需要任何权限,这意味着任何与 FourGoats 应用程序安装在统一设备上的恶意应用程序可以访问该设备的位置,这是非常危险的。
使用 Drozer 确定下该APP的攻击面:
接着可以使用以下命令,调用内部服务组件:
run app.service.start --action 服务名 --component 包名 服务名
run app.service.start --action org.owasp.goatdroid.fourgoats.services.LocationService --component org.owasp.goatdroid.fourgoats org.owasp.goatdroid.fourgoats.services.LocationService
执行以下命令,观察状态栏中的位置标志和 GPS 位置正在由 FourGoats 应用程序访问:
广播接收器
Broadcast Receive 广播接收器:应用可以使用它对外部事件进行过滤只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面,然而它们可以启动一个 Activity 或 Serice 来响应它们收到的信息,或者用 NotificationManager 来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。
当应用广播接收器默认设置exported='true'
,导致应用可能接收到第三方恶意应用伪造的广播,利用这一漏洞,攻击者可以在用户手机通知栏上推送任意消息,通过配合其它漏洞盗取本地隐私文件和执行任意代码。Android 可以在配置文件中声明一个receiver或者动态注册一个receiver来接收广播信息,攻击者假冒APP构造广播发送给被攻击的receiver,是被攻击的APP执行某些敏感行为或者返回敏感信息等,如果receiver接收到有害的数据或者命令时可能泄露数据或者做一些不当的操作,会造成用户的信息泄漏甚至是财产损失。
下面使用 fourgoats.apk 测试广播接收器组件,查看 fourgoats 该 APP 的可攻击点,可以看到存在 广播问题,进一步查看对外的 broadcast 组件信息:
查看反编译出的 AndroidManifest.xml 文件,可看到 receiver 的 exported 设置未进行设置,说明存在越权问题,可发送恶意广播,伪造消息等。
进一步查看源代码,发现需要两个参数 phoneNumber 和 message:
发送恶意广播
发现利用该漏洞可发送恶意广播包:
run app.broadcast.send --action org.owasp.goatdroid.fourgoats.SOCIAL_SMS --extra string phoneNumber 1234 --extra string message pwnd!
如下图所示:
拒绝服务攻击
输入命令:run app.broadcast.send --action <action>
,尝试拒绝服务攻击检测,向广播组件发送不完整 intent 使用空 extras,可看到应用停止运行:
总结
1、当组件为私有组件时,建议设置 exported 的值为 false(exported查找方法,搜索 android:exported);
2、当组件为公有组件时,建议对其进行权限控制。