前言
相信大家都用过JustTrustMe这个Xposed插件,但是为什么要用,它是拿来干啥的,估计大部门人都会有点懵逼,一开始我用的时候就是一脸懵逼,网上的资料都告诉你要安装这个插件,但是为什么要装却没有讲的很清楚,下面以Android开发的角度来一一讲述下JustTrustMe这个插件的作用以及原理。
SSL Pinning
Android 证书固定写法如下(以URLConnection为例):
当访问的域名是 预埋证书内的域名时,正常返回数据,如下:
当访问 非预埋证书内的域名时,如百度,结果如下:
显示证书链错误,
也就是说证书固定,只能访问预埋证书内的域名,访问其他的域名都会报错,从而导致了我们在使用burp抓包时,会出现抓不到数据包的情况。
当手机设置了burp代理,流量会经过burp,会读取burp的https证书,由于burp的证书不是app内预埋的,导致请求失败,burp的Alerts选项卡中会出现错误The client failed to negotiate an SSL connection to test.lxhsec.com:443: Received fatal alert: certificate_unknown
,具体如下:
SSL Pinning成功的防止了大多数的中间人攻击。
SSL Pinning Bypass
绕过也很简单,
通过hook的方式,将SSLContext实例绑定的TrustManager置为空实现,
具体代码如下(Frida实现):
function AndroidMain(){var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');var TrustManager;try {TrustManager = Java.registerClass({name: 'org.wooyun.TrustManager',implements: [X509TrustManager],methods: {checkClientTrusted: function(chain, authType) {},checkServerTrusted: function(chain, authType) {},getAcceptedIssuers: function() {return [];}}});var TrustManagers = [TrustManager.$new()];var SSLContext = Java.use('javax.net.ssl.SSLContext');SSLContext.init.overload('[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom').implementation = function() {console.log("执行替换")this.init.overload('[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom').call(this, null, TrustManagers, null);}} catch (e) {console.log("error: " + e.message);}}
通过HTTPDecrypt加载脚本,
继续访问 非预埋证书内的域名时,如百度,结果如下:
burp抓包也是ok的,如下:
而JustTrustMe这个Xposed插件的原理,就是将不同(尽可能多)的请求库(URLConnection、okhttp等)的证书固定写法 针对性的替换为空实现,从而让测试人员遇到App证书固定时可以直接抓到数据包进行测试。
上述代码以及frida完整代码都打包到网盘了,
回复ssl1
即可下载。
持久性还得靠Xposed、用Frida只图一乐。
本文始发于微信公众号(Khan安全攻防实验室):Android(SSL/TLS Pinning) & SSL Pinning Bypass
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论