Android平台HTTPS抓包全方案

/ 作者简介 /
本篇文章转自MegatronKing的博客,分享了Android中https抓包相关的解决方案,希望对大家有所帮助!
/ 前言 /
HTTP协议发展至今已经有二十多年的历史,整个发展的趋势主要是两个方向:效率和安全 。效率方面,从HTTP1.0的一次请求一个连接,到HTTP1.1的连接复用,到SPDY/HTTP2的多路复用,到QUIC/HTTP3的基于UDP传输,在效率方面越来越高效 。安全方面,从HTTP的明文,到HTTP2强制使用TLSv1.2,到QUIC/HTTP3强制使用TLSv1.3,越来越注重数据传输的安全性 。总而言之,HTTP协议的发展对用户是友好的,但是对开发者而言却不那么友善 。
抓包是每个程序员的必修技能之一,尤其是在接口调试和程序逆向方面具有广阔的用途 。但是,随着越来越多的通信协议使用加密的HTTPS,而且系统层面也开始强制规定使用HTTPS,抓包似乎是显得越来越难了 。
本篇博客,主要详解Android平台下,HTTPS抓包的常见问题以及解决办法 。工欲善其事必先利其器,博客中以HttpCanary作为抓包工具进行讲解 。更多HttpCanary的资料,请见:
GitHub地址:

https://github.com/MegatronKing/HttpCanary
/ 抓包原理 /
几乎所有网络数据的抓包都是采用中间人的方式(MITM),包括大家常用的Fiddler、Charles等知名抓包工具,HttpCanary同样是使用中间人的方式进行抓包 。
Android平台HTTPS抓包全方案

文章插图
 
从上面这个原理图,可以看出抓包的核心问题主要是两个:
  • MITM Server如何伪装成真正的Server
  • MITM Client如何伪装成真正的Client
第一个问题,MITM Server要成为真正的Server,必须能够给指定域名签发公钥证书,且公钥证书能够通过系统的安全校验 。比如Client发送了一条https://www.baidu.com/的网络请求,MITM Server要伪装成百度的Server,必须持有www.baidu.com域名的公钥证书并发给Client,同时还要有与公钥相匹配的私钥 。
MITM Server的处理方式是从第一个SSL/TLS握手包Client Hello中提取出域名www.baidu.com,利用应用内置的CA证书创建www.baidu.com域名的公钥证书和私钥 。创建的公钥证书在SSL/TLS握手的过程中发给Client,Client收到公钥证书后会由系统会对此证书进行校验,判断是否是百度公司持有的证书,但很明显这个证书是抓包工具伪造的 。为了能够让系统校验公钥证书时认为证书是真实有效的,我们需要将抓包应用内置的CA证书手动安装到系统中,作为真正的证书发行商(CA),即洗白 。这就是为什么,HTTPS抓包一定要先安装CA证书 。
第二个问题,MITM Client伪装成Client 。由于服务器并不会校验Client(绝大部分情况),所以这个问题一般不会存在 。比如Server一般不会关心Client到底是Chrome浏览器还是IE浏览器,是Android App还是IOS App 。当然,Server也是可以校验Client的,这个后面分析 。
/ 安装CA证书 /
【Android平台HTTPS抓包全方案】抓包应用内置的CA证书要洗白,必须安装到系统中 。而Android系统将CA证书又分为两种:用户CA证书和系统CA证书 。顾明思议,用户CA证书是由用户自行安装的,系统CA证书是由系统内置的,很明显后者更加真实有效 。
系统CA证书存放在/etc/security/cacerts/目录下,名称是CA证书subjectDN的Md5值前四位移位取或,后缀名是.0,比如00673b5b.0 。考虑到安全原因,系统CA证书需要有Root权限才能进行添加和删除 。
对于非Root的Android设备,用户只能安装用户CA证书 。
无论是系统CA证书还是用户CA证书,都可以在设置->系统安全->加密与凭据->信任的凭据中查看:
Android平台HTTPS抓包全方案

文章插图
 
/ Android7.0的用户CA限制 /
Android从7.0开始系统不再信任用户CA证书(应用targetSdkVersion >= 24时生效,如果targetSdkVersion < 24即使系统是7.0+依然会信任) 。也就是说即使安装了用户CA证书,在Android 7.0+的机器上,targetSdkVersion >= 24的应用的HTTPS包就抓不到了 。
比如上面的例子,抓包工具用内置的CA证书,创建了www.baidu.com域名的公钥证书发给Client,系统校验此证书时发现是用户CA证书签发的,sorry 。。。那么,我们如果绕过这种限制呢?已知有以下四种方式(低于7.0的系统请忽略) 。
配置networkSecurityConfig如果我们想抓自己的App,只需要在AndroidManifest中配置networkSecurityConfig即可:
<?xml version="1.0" encoding="utf-8"?><manifest ... ><application android:networkSecurityConfig="@xml/network_security_config"... >...</application></manifest>


推荐阅读