APP渗透测试
APK敏感信息收集
使用工具快速扫描
推荐 apkleaks https://github.com/dwisiswant0/apkleaks
可以发现比如云主机的key,服务器真实IP、其他服务的密钥等信息。
python apkleaks.py -f "C:\Users\Administrator\Desktop\app\test.apk"
反编译APK
一个apk包的本质是一个zip格式的压缩包,我们可以直接使用解压缩工具进行解压。
1)检查 classes.dex 硬编码
使用MT管理器查看apk,检查apk包中是否存在硬编码的敏感信息。
重点查看classes.dex文件反编译后是否有硬编码的敏感信息。
APK文件结构如下
2)检查SharedPreferences 配置文件
检查客户端程序存储在手机中的 SharedPreferences 配置文件是否存储、泄露敏感信息。
可以使用MT管理器查看(手机需要root)
• 用MT管理器查看下APK的应用包名
• 查看路径/data/data/<应用包名>/shared_prefs/<应用包名>_preferences.xml
• 可以查看保存的SharedPreferences键值对信息
3)检查SQLite数据库
检查客户端程序存储在手机中的SQLite 数据库文件是否保存、泄漏敏感信息。
将路径/data/data/<应用包名>/databases/下的sqlite3类型的数据库文件
用文件管理器导出来用可视化工具查看
4)检查logcat日志
APP客户端本地 log 运行日志是否打印、泄露用户敏感信息(使用adb即可查看)。
• 按照应用过滤日志
pm list packages -3 #查看非系统的第三方应用包名
logcat | grep <应用包名或者关键字>
然后运行要检查的APP即可实时查看日志。
APP抓包
一、设置代理
1)Burp代理设置为局域网的IP
2)模拟器设置桥接模式,和代理工具Burp所在宿主机处于同一局域网
设置模拟器的网络代理为Burp的地址
3)模拟器访问Burp代理的IP,下载并安装CA证书
下载完先把后缀改为cer
夜神模拟器是在WLAN设置中点高级安装证书
或者有的模拟器是从设置中搜索安全,打开加密与凭据选项选择从SD卡安装证书
二、安装系统证书
抓到的HTTPS包都是乱码,因为安卓高版本即7.0之后,app可以只信任指定证书和系统内置的证书,后续用户安装的证书是不生效的。所以需要将Burp的CA证书安装到系统内部。
# 转为pem格式
openssl x509 -inform DER -in cacert.der -out cacert.pem
# 重命名为<hash值>.0
mv cacert.pem `openssl x509 -inform PEM -subject_hash_old -in cacert.pem |head -1`'.0'
将xxxhash.0证书文件复制到系统根信任证书目录即可
或者直接使用面具的movecert模块
https://github.com/ys1231/MoveCertificate
加固绕过
root检测绕过
通过Magisk本身的排除列表或者Shamiko插件来绕过。
1)用adb将shamiko推送到手机上
adb push Shamiko-v1.0.1-300-release.zip /sdcard/Download/Shamiko-v1.0.1-300-release.zip
2)打开面具,进入模块,选择从本地安装,将zip刷入,点击重启
3)再次打开面具,点击右上角齿轮,配置排除列表,将绕过的APP排除,打开APP就没有提示了
代理检测绕过
使用VPN代理:https://github.com/ys1231/appproxy
frida检测绕过
https://github.com/frida/frida 现已经支持自动构建反检测
windows安装客户端
pip3 install Frida
pip3 install frida-tools
pip3 install objection
ssl Pinning证书绑定绕过
有些APP有预埋证书验证,遇到Burp的证书不能通过验证还是不能抓包。
使用frida进行hook绕过,使用通用的绕过脚本或自己编写。
1)查找设备的arch版本,下载对应的frida
adb shell getprop ro.product.cpu.abi
2)推送frida到手机上
下载后解压,把解压后的文件使用adb命令上传到设备
#推送到设备
adb push C:\frida-server /data/local/tmp
#授予执行权限
adb shell chmod 777 /data/local/tmp/frida-server
#启动firdas-erver
adb shell /data/local/tmp/frida-server &
4)打开新终端,列出服务列表,找到包名
frida-ps -U
3)使用Hook注入脚本
https://github.com/fdciabdul/Frida-Multiple-Bypass
#客户端注入
frida -U -f com.package.name --no-pause -l C:\bypass.js
另一个hook脚本
/*
Android SSL Re-pinning frida script v0.2 030417-pier
$ adb push burpca-cert-der.crt /data/local/tmp/cert-der.crt
$ frida -U -f it.app.mobile -l frida-android-repinning.js --no-pause
https://techblog.mediaservice.net/2017/07/universal-android-ssl-pinning-bypass-with-frida/
UPDATE 20191605: Fixed undeclared var. Thanks to @oleavr and @ehsanpc9999 !
*/
setTimeout(function(){
Java.perform(function (){
console.log("");
console.log("[.] Cert Pinning Bypass/Re-Pinning");
var CertificateFactory = Java.use("java.security.cert.CertificateFactory");
var FileInputStream = Java.use("java.io.FileInputStream");
var BufferedInputStream = Java.use("java.io.BufferedInputStream");
var X509Certificate = Java.use("java.security.cert.X509Certificate");
var KeyStore = Java.use("java.security.KeyStore");
var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory");
var SSLContext = Java.use("javax.net.ssl.SSLContext");
// Load CAs from an InputStream
console.log("[+] Loading our CA...")
var cf = CertificateFactory.getInstance("X.509");
try {
var fileInputStream = FileInputStream.$new("/data/local/tmp/cert-der.crt");
}
catch(err) {
console.log("[o] " + err);
}
var bufferedInputStream = BufferedInputStream.$new(fileInputStream);
var ca = cf.generateCertificate(bufferedInputStream);
bufferedInputStream.close();
var certInfo = Java.cast(ca, X509Certificate);
console.log("[o] Our CA Info: " + certInfo.getSubjectDN());
// Create a KeyStore containing our trusted CAs
console.log("[+] Creating a KeyStore for our CA...");
var keyStoreType = KeyStore.getDefaultType();
var keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
console.log("[+] Creating a TrustManager that trusts the CA in our KeyStore...");
var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
var tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
console.log("[+] Our TrustManager is ready...");
console.log("[+] Hijacking SSLContext methods now...")
console.log("[-] Waiting for the app to invoke SSLContext.init()...")
SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").implementation = function(a,b,c) {
console.log("[o] App invoked javax.net.ssl.SSLContext.init...");
SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").call(this, a, tmf.getTrustManagers(), c);
console.log("[+] SSLContext initialized with our custom TrustManager!");
}
});
},0);