本文共 5230 字,大约阅读时间需要 17 分钟。
最近,公司QC在App测试抓包中,一直反应的一个问题,就是高版本的android手机在进行线上环境的抓包时,无法查看https的内容体。有需求,就要去解决,对吧。这个问题一个是线上环境是Https的,另一个android手机的版本查明是android6.0手机,还有一个信息就是QC使用的抓包工具,为主流的fiddler或者Charles。
解析一下抓包工具,如果没有什么特别配置,大多数的App还是使用单向认证或者不认证,只是跑一下https的安全加密而已,并没有太多的东西。所以抓包工具,可以直接对server端接口进行访问,只要把请求和响应处理好,为了保持类似的原样,抓包工具作为网络代理,就不会把服务端证书给终端了,因为抓包代理已经使用了证书,并且利用公钥和https的协议建立好了通信,所以抓包代理再返回客户端的时候,这一段的通信也是象征性地使用https。
其实,个人认为,抓包代理完全不需要把解密后的网络数据,再次加密,因为,我们之所以使用抓包工具,无非就是看到明文内容,再次加密给客户端有点画蛇添足。实际上,多想一点,也不是这样的。。首先抓包代理,起码的原则,就是尽量做到客户端无感知,这是基本设计原则,然后客户终端每个应用程序的网络请求由各个应用程序自己控制,而应用程式的网络请求多数都是应用开源或者市面上经常用到的框架library,每个library对协议的支持各有不同。尽量地还原协议本身,也是让程序尽量可以无感知。比如说,应用程序对一个地址是否使用了https都是采用url上面的字符对比,如果是https,显而易见,会和http走完全不同的连接协议,抓包代理其实就是一个中间人,把私自把数据内容修改掉了,终端程序的网络请求就无法处理了。so,抓包代理还是需要把得到数据,再次使用https的方式返回给客户端机器。
下一个问题,为什么客户端机器不能使用使用自己服务端的证书呢,非要使用抓包工具提供的证书,这个就简单了,因为,抓包工具的代理,是一种全局代理,当然其实也不是,用户可以设定哪些https的连接需要抓包代理去做解密,所有已经解密的连接,才会在抓包工具上看到网络请求明文。已经还原明文的连接,必须使用逆过程还原过去,这样才能让客户端正常使用https协议,我们知道,https使用非对称协商加密,代理和服务,代理与应用都是C/S结构,客户端得到公钥去加密随机序列作为对称密码只有服务端的私钥才能解开。网络代理可以把服务端公钥转给客户端,但是客户端拿到公钥加密的密码无可奈何,因为他得不到服务端的私钥(服务端的绝密),所以在代理的时候服务端会在做https的透传的时候,会使用抓包工具自己的证书和私钥。与此相对应,客户端如果使用了证书的校验机制,就需要把抓包工具的证书添加到自己的设备,或者应用程序的网络环境中。我想这里抓包工具的证书必须是自定义的因为可以加密所有的网络连接,就会匹配所有的domain域名,CA肯定不会办理这种级别的证书。
这里先要引出一个小问题,就是如果客户端应用程序在进行证书校验的时候,验证失败怎么办,这个时候https的建立就失败了,怎么办,难道抓包代理就不让我联网了吗。。这里我个人发现算是独断的吧,如果在客户端证书无法校验的时候,抓包代理作为一个工具,会退步(这个没有验证),不再解密验证失败的连接,我们如果在这个时候抓到的就是密文了。
****************下方高能,隔离标注(说点干货,(show me the fucking code))*********************
Https代理工作流程:
[客户端] -HTTP CONNECT a.b.c.d:port-> [代理] -TCP SYN-> [服务器] [客户端] <- 200 OK- [代理] <-TCP SYN ACK- [服务器] # 连接成功的200 [客户端] -SSL CLIENT HELLO-> [代理] -SSL CLIENT HELLO-> [服务器] # SSL握手包1 [客户端] <-SSL SERVER HELLO- [代理] <-SSL SERVER HELLO/CERTIFICATE等- [服务器] # SSL握手包2 [客户端] -SSL CLIENT CERTIFICATE等-> [代理] -SSL CLIENT CERTIFICATE等-> [服务器] # SSL握手包3 [客户端] <-SSL SERVER FINISHED- [代理] <-SSL SERVER FINISHED- [服务器] # SSL握手包4 [客户端] -SSL加密的HTTP GET-> [代理] -SSL加密的HTTP GET-> [服务器] [客户端] <-SSL加密的200 OK- [代理] <-SSL加密的200 OK- [服务器]Https客户端不做任何验证和校验:
/** * ChopeHttpsUtils,for test. * Created by Hunter on 2018/4/10 0010. */class ChopeHttpsUtils { public static void trustAll() { TrustManager[] trustAllCerts = new TrustManager[1]; TrustManager tm = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }; trustAllCerts[0] = tm; HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String urlHostName, SSLSession session) { System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost()); return true; } }; SSLContext sc = null; try { sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, null); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (KeyManagementException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } HttpsURLConnection.setDefaultHostnameVerifier(hv); }}**************** 下方再次高能,Android基友们注意*********************
应该说这里才是点题的正文。这里聊的,不是android使用各种网络框架如果配置证书(系统,自定义等),也不说单向验证和双向验证,也不讲Java的秘钥体系,也不讲openSSl或者keytool(如果以后有机会,可以聊一聊这些,尤其是Java的秘钥体系故事挺多,请准备好小龙虾与啤酒)。
这里只聊一种情况,就是android App默认使用的根证书的情况。Android N (24,7.0)和其之上的一个安全行为变更,不排除,有些OEM厂商,把这个行为变更迁徙到自己的低版本或者更高版本的android系统。
当target指向24,或者之上版本的应用,系统默认不再信任用户(App)或者系统自定义添加的证书。
所有运行AndroidN的系统设备提供标准统一的一套系统CA证书,不再有设备厂商自定义的证书。
如果用户需要使用自定义证书,或者系统的添加证书,需要在 Manifest Application中单独配置 networkSecurityConfig 标签,这个标签对应一个xml资源。
几个xml例子,三种基类标签,debug-overrides,domain-config,base-config。可以合并。
internal.example.com
userCaDomain.com otherUserCaDomain.com
sensitive.example.com
首先要说的是,这里是AndroidN的应为变更,如果不适用系统级别的功能,可以不做适配,代码功能仍然有限。
如果,你是用来抓https包,那么就要需要配置一下了。不过,为了面向未来,面向安全,我建议开发者,我技术领导,弹性调配。我个人感觉,Android的这个变更,更多的是政策上的东西,其中多少有些强制未来全网https一样,这里面更多的味道应该政策居多。
刚开始的时候说了。如果想了解Java秘钥体系的,可以留个言什么的。。我也想找个机会聊一聊,毕竟憋在肚子里面难受,跟大家分享一下,共同进步。
转载地址:http://ijegi.baihongyu.com/