前言
在安卓手机安装上应用后,使用抓包工具如burpsuite无法抓包(手机用户凭证已安装burp的证书),此时考虑存在抓不到包的原因可以分为以下四种情况:
- 应用只信任系统证书,不信任我们安装在用户凭证的证书。
- 应用做了单向校验,一般情况下是客户端校验服务端证书是否是正确来源的,也有服务端校验客户端证书的。
- 应用做了双向校验,也就是服务端和客户端互相校验证书来源的正确性。
- 应用不走http系统代理。
参考链接
【1】HTTPS单向认证、双向认证、抓包原理、反抓包策略
【2】HTTPS实战之单向验证和双向验证
正文
在安装了代理软件证书到手机用户凭证中后(这里以burpsuite举例,后续均以该代理软件说明),使用burp设置代理后,应用无法访问网络,即抓取不到数据包,这里可以考虑的情况有三种,即前言中的1,2,3种情况。
- 只信任系统证书解决方案
这个只信任系统证书其实是在使用安卓SDK的API24及以上的应用系统中默认配置的,详情可参考链接【3】,因此使用高于API24以上的sdk开发的应用默认不信任安装的用户证书,这里介绍两种该问题解决方案。
方案一:在手机root的情况下,将我们的证书以<Certificate_Hash>.<Number>
的名称
导入到/system/etc/security/cacerts/
,一般后缀为0,这里需要使用到openssl进行计算我们导出证书的hash值。可参考链接【5】进行安装,这里列出计算hash值的命令如下:
openssl x509 -inform der -subject_hash_old -in bp.cer
或者
openssl x509 -subject_hash_old -in bp.pem
注意
:这里需要强调的是,安装上系统证书,可到手机系统信任的凭证中查看是否已经有该证书显示信息,若存在就无需重启手机,因为对于高版本系统手机存在重启后证书失效的问题,在系统信任凭证中无法找到安装的证书,可到
/system/etc/security/cacerts/
目录下查看证书的大小是否为0kb,若为0即需要重新复制一份过来,如果多次尝试仍然为0,可考虑重启尝试。
方案二:可参考官网【3】的详细解决方案,即通过反编译APP应用客户端,在客户端中添加配置信息,以让APP信任我们的用户凭证,由于该方法是修改客户端代码,即存在应用加固无法反编译或者反编译以及回编译出现各种报错问题,
这里以无加固,反编译以及回编译正常的应用来说明(当然大家遇到加固应用也可尝试进行反编译,回编译处理各种报错)。
首先使用反编译工具AndroidKiller反编译应用,在res/xml目录下找到network_security_config.xml添加如下代码,一般是存在该文件,只需要添加
<certificates src="user" />即可,没有的话自己创建一个文件。
<network-security-config>
<domain-config>
<domain includeSubdomains="true">userCaDomain.com</domain>
<domain includeSubdomains="true">otherUserCaDomain.com</domain>
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</domain-config>
</network-security-config>
然后在AndroidManifest.xml中添加注册信息
android:networkSecurityConfig="@xml/network_security_config"
最后保存,回编译APP生成新的apk文件,使用新的apk文件进行抓包测试。
参考链接
【3】Android Developers Blog: Changes to Trusted Certificate Authorities in Android Nougat (googleblog.com)
【4】Android 7.0 之后抓包 unknown 和证书无效的解决方案,手机需root
【5】系统证书安装
- 单向证书校验解决方案
单向证书校验一般是指客户端对服务端的证书校验,遇到该问题一般可考虑使用root手机进行安装xposed框架及justtrustme模块进行绕过该限制。如果手机未root,可考虑使用frida的hook方式进行绕过,这里贴出参考链接【6】,里面详细说明了frida的hook进行绕过sslPinning的限制,为避免链接失效,贴出复制出的文字及脚本。对于服务端校验客户端证书的情况放在双向证书校验解决方案中进行说明。
Frida的hook方案脚本见下:
抓取HTTPS的数据包
Frida绕过SSL单向校验
遇到JustTrustMe无法绕过SSL单向校验的情况, 接触了Frida, 就尝试用DBI的方法绕过SSL的单向校验,
参考文章https://techblog.mediaservice.net/2017/07/universal-android-ssl-pinning-bypass-with-frida/
Frida这里就不详细地说明Frida的安装方法及使用方法了。
设置Fiddler代理, 在本地下载Fiddler的证书, 将证书直接重命名为cert-der.crt。之后将证书push到/data/local/tmp目录下, 在adb shell里输入./frida-server &再在PC端进行操作。
新建一个frida-android-repinning.js文件, 详细代码如下:
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);
在cmd, 输入如下命令:
$ 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
在关闭应用的情况下(避免Magisk Hide处于开启状态), 可得到回显并绕过SSL pinning。
参考链接:https://xz.aliyun.com/t/6551#toc-9
参考链接
【6】Frida绕过SSL单向校验
- 双向证书校验解决方案
对于使用双向校验的应用需要在客户端本地寻找到证书,以及在客户端代码中寻找到证书密钥,然后安装到我们的代理软件中去。具体操作步骤也可查看链接【6】进行查看具体实际案例操作步骤。
- 不走系统http代理解决方案
对于设置不走系统代理的最直接明显的效果就是在设置好burp代理,依然可以正常使用APP,APP的网络通讯未受到丝毫影响。解决不走系统http代理的方式可以采用vpn代理方式进行绕过,即先将手机流量通过vpn发送到电脑代理软件,再通过代理软件抓包查看。使用vpn代理抓包可参考下一篇文章《charles+socks5代理+burpsuite抓包》。