Android平台HTTPS抓包全方案

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
.cn 域名,1个 12个月
简介: 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地址免费获取

抓包原理

几乎所有网络数据的抓包都是采用中间人的方式(MITM),包括大家常用的Fiddler、Charles等知名抓包工具,HttpCanary同样是使用中间人的方式进行抓包。

 

从上面这个原理图,可以看出抓包的核心问题主要是两个:

  • 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证书 /

抓包应用内置的CA证书要洗白,必须安装到系统中。而Android系统将CA证书又分为两种:用户CA证书和系统CA证书。顾明思议,用户CA证书是由用户自行安装的,系统CA证书是由系统内置的,很明显后者更加真实有效。

系统CA证书存放在/etc/security/cacerts/目录下,名称是CA证书subjectDN的Md5值前四位移位取或,后缀名是.0,比如00673b5b.0。考虑到安全原因,系统CA证书需要有Root权限才能进行添加和删除。

对于非Root的Android设备,用户只能安装用户CA证书。

无论是系统CA证书还是用户CA证书,都可以在设置->系统安全->加密与凭据->信任的凭据中查看:

 

/ 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> 
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
            <certificates src="user" />
        </trust-anchors>
    </base-config>
</network-security-config> 

这样即表示,App信任用户CA证书,让系统对用户CA证书的校验给予通过。更多相关信息,详见

Network security configuration:

https://developer.android.com/training/articles/security-config

调低targetSdkVersion < 24

如果想抓一个App的包,可以找个历史版本,只需要其targetSdkVersion < 24即可。然而,随着GooglePlay开始限制targetSdkVersion,现在要求其必须>=26,2019年8月1日后必须>=28,国内应用市场也开始逐步响应这种限制。绝大多数App的targetSdkVersion都将大于24了,也就意味着抓HTTPS的包越来越难操作了。

平行空间抓包

如果我们希望抓targetSdkVersion >= 24的应用的包,那又该怎么办呢?我们可以使用平行空间或者VirtualApp来曲线救国。平行空间和VirtualApp这种多开应用可以作为宿主系统来运行其它应用,如果平行空间和VirtualApp的targetSdkVersion < 24,那么问题也就解决了。

在此,我推荐使用平行空间,相比部分开源的VirtualApp,平行空间运行得更加稳定。但必须注意平行空间的版本4.0.8625以下才是targetSdkVersion < 24,别安装错了。当然,HttpCanary的设置中是可以直接安装平行空间的。

安装到系统CA证书目录

对于Root的机器,这是最完美最佳的解决方案。如果把CA证书安装到系统CA证书目录中,那这个假CA证书就是真正洗白了,不是真的也是真的了。由于系统CA证书格式都是特殊的.0格式,我们必须将抓包工具内置的CA证书以这种格式导出,HttpCanary直接提供了这种导出选项。

操作路径:设置 -> SSL证书设置 -> 导出HttpCanary根证书 -> System Trusted(.0)。

 

PS. 很不幸的HttpCanary v2.8.0前导出的证书名称可能不正确,建议升级到v2.8.0以上版本操作。

导出.0格式的证书后,可以使用MT管理器将.0文件复制到/etc/security/cacerts/目录下,或者通过adb remount然后push也可(这里稍微提一下,别在sdcard里找这个目录)。

/ Firefox证书安装 /

火狐浏览器Firefox自行搞了一套CA证书管理,无论是系统CA证书还是用户CA证书,Firefox通通都不认可。这种情况,我们需要将CA证书通过特殊方式导入到Firefox中,否则Firefox浏览网页就无法工作了。

HttpCanary v2.8.0版本提供了Firefox证书导入选项。在设置 -> SSL证书设置 -> 添加HttpCanary根证书至Firefox 中:

 

点击右上角复制按钮将url复制到粘贴板,然后保持此页面不动,打开Firefox粘贴输入复制的url。

 

出现下载证书弹框后,一定要手动勾上:信任用来标志网站和信任用来标志电子邮件用户。然后确定即可。

/ 公钥证书固定 /

证书固定(Certificate Pinning)是指Client端内置Server端真正的公钥证书。在HTTPS请求时,Server端发给客户端的公钥证书必须与Client端内置的公钥证书一致,请求才会成功。

在这种情况下,由于MITM Server创建的公钥证书和Client端内置的公钥证书不一致,MITM Server就无法伪装成真正的Server了。这时,抓包就表现为App网络错误。已知的知名应用,比如饿了么,就采用了证书固定。

另外,有些服务器采用的自签证书(证书不是由真正CA发行商签发的),这种情况App请求时必须使用证书固定。

证书固定的一般做法是,将公钥证书(.crt或者.cer等格式)内置到App中,然后创建TrustManager时将公钥证书加进去。很多应用还会将内置的公钥证书伪装起来或者加密,防止逆向提取,比如饿了么就伪装成了png,当然对公钥证书伪装或者加密没什么太大必要,纯粹自欺欺人罢了。

证书固定对抓包是个非常麻烦的阻碍,不过我们总是有办法绕过的,就是麻烦了点。

JustTrustMe破解证书固定

Xposed和Magisk都有相应的模块,用来破解证书固定,实现正常抓包。破解的原理大致是,Hook创建SSLContext等涉及TrustManager相关的方法,将固定的证书移除。

基于VirtualApp的Hook机制破解证书固定

Xposed和Magisk需要刷机等特殊处理,但是如果不想刷机折腾,我们还可以在VirtualApp中加入Hook代码,然后利用VirtualApp打开目标应用进行抓包。当然,有开发者已经实现了相关的功能。详见:

案例1:

https://github.com/PAGalaxyLab/VirtualHook

案例2:

https://github.com/rk700/CertUnpinning

不过,这里CertUnpinning插件的代码有点问题,要改改。

导入真正的公钥证书和私钥

如果Client固定了公钥证书,那么MITM Server必须持有真正的公钥证书和匹配的私钥。如果开发者具有真正服务端的公钥证书和私钥,(比如百度的公钥证书和私钥百度的后端开发肯定有),如果真有的话,可以将其导入HttpCanary中,也可以完成正常抓包。

在设置 -> SSL证书设置 -> 管理SSL导入证书 中,切换到服务端,然后导入公钥证书+私钥,支持.p12和.bks格式文件。

/ 双向认证 /

SSL/TLS协议提供了双向认证的功能,即除了Client需要校验Server的真实性,Server也需要校验Client的真实性。这种情况,一般比较少,但是还是有部分应用是开启了双向认证的。比如匿名社交应用Soul部分接口就使用了双向认证。使用了双向认证的HTTPS请求,同样无法直接抓包。

关于双向认证的原理

首先,双向认证需要Server支持,Client必须内置一套公钥证书 + 私钥。在SSL/TLS握手过程中,Server端会向Client端请求证书,Client端必须将内置的公钥证书发给Server,Server验证公钥证书的真实性。

注意,这里的内置的公钥证书有区别于前面第5点的公钥证书固定,双向认证内置的公钥证书+私钥是额外的一套,不同于证书固定内置的公钥证书。

如果一个Client既使用证书固定,又使用双向认证,那么Client端应该内置一套公钥证书 + 一套公钥证书和私钥。第一套与Server端的公钥证书相同,用于Client端系统校验与Server发来的证书是否相同,即证书固定;第二套SSL/TLS握手时公钥证书发给Server端,Server端进行签名校验,即双向认证。

用于双向认证的公钥证书和私钥代表了Client端身份,所以其是隐秘的,一般都是用.p12或者.bks文件+密钥进行存放。由于是内置在Client中,存储的密钥一般也是写死在Client代码中,有些App为了防反编译会将密钥写到so库中,比如S匿名社交App,但是只要存在于Client端中都是有办法提取出来的。

双向认证抓包

这里以S匿名社交App为例,讲解下如何抓取使用了双向认证的App的HTTPS包。如果服务器使用了Nginx且开启了双向认证,抓包时会出现400 Bad Request的错误,如下:

 

 

有些服务器可能不会返回404,直接请求失败。接下来看,如何使用HttpCanary配置双向认证抓包。

首先,解压APK,提取出.p12或者.bks文件,二进制的文件一般存放都在raw或者assets目录。

 

将client.p12文件导入手机,然后在HttpCanary的设置 -> SSL证书设置 -> 管理SSL导入证书中,切换到客户端(因为需要配给MITM Client),然后导入.p12文件。

由于双向认证的公钥证书和私钥是受密钥保护的,所以需要输入密码:

 

一般通过逆向可以从APK中提取出密钥,具体操作这里略过。输入密钥后,需要输入映射域名,这里使用通配符*映射所有相关域名:

 

导入完成后如下:

 

可以点进证书详情查看细节,这个client.p12文件包含公钥证书和私钥,是用于双向认证的。

 

配置完成后,重新进行抓包,看看效果。

 

可以看到,之前400 Bad Request的两个要求双向认证的请求成功了!

/ SSL重协商 /

有些服务器可能会开启SSL重协商,即SSL/TLS握手成功后发送请求时服务器会要求重新握手。这种情况一般比较少,但是也不排除,已知的应用比如 10000社区 就使用了SSL重协商。

由于Android系统对SSL重协商是有限支持,所以部分系统版本抓包会失败,表现为网络异常。在Android 8.1以下,SslSocket是完全支持SSL重协商的,但是SSLEngine却是不支持SSL重协商的,而HttpCanary解析SSL/TLS使用的是SSLEngine。在Android 8.1及以上,SSLEngine和SslSocket统一了实现,故是支持SSL重协商的。

所以,如果确认服务器使用了SSL重协商,请使用8.1及以上版本系统进行抓包。

/ 非Http协议抓包 /

如果确认了以上几点,HttpCanary仍然抓包失败,那么极有可能使用的并非是HTTP协议。比如像微信聊天,视频直播等,使用的就不是HTTP协议,这种情况需要使用其它的抓包工具,比如Packet Capture这种直接解析TCP/UDP协议的,但是往往非HTTP协议的数据包即使抓到了也无法解析出来,因为大概率都是二进制而非文本格式的。

/ 总结 /

抓包是个技术活儿,需要对网络协议有大致的了解,对抓包感兴趣的同学可以多查阅TCP、UDP、SSL/TLS、HTTP等相关资料。

HttpCanary是专业的HTTP协议抓包工具,专注HTTP协议三十年(吹过头了),不过目前还不支持QUIC/HTTP3这种新协议,等QUIC/HTTP3正式应用起来再说吧。


相关文章
|
2月前
|
Java Android开发 Swift
安卓与iOS开发对比:平台选择对项目成功的影响
【10月更文挑战第4天】在移动应用开发的世界中,选择合适的平台是至关重要的。本文将深入探讨安卓和iOS两大主流平台的开发环境、用户基础、市场份额和开发成本等方面的差异,并分析这些差异如何影响项目的最终成果。通过比较这两个平台的优势与挑战,开发者可以更好地决定哪个平台更适合他们的项目需求。
121 1
|
3月前
|
IDE Android开发 iOS开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
【9月更文挑战第27天】在移动应用开发的世界中,Android和iOS是两个主要的操作系统平台。每个系统都有其独特的开发环境、工具和用户群体。本文将深入探讨这两个平台的关键差异点,并分析这些差异如何影响应用的性能、用户体验和最终的市场表现。通过对比分析,我们将揭示选择正确的开发平台对于确保项目成功的重要作用。
|
14天前
|
IDE 开发工具 Android开发
移动应用开发之旅:探索Android和iOS平台
在这篇文章中,我们将深入探讨移动应用开发的两个主要平台——Android和iOS。我们将了解它们的操作系统、开发环境和工具,并通过代码示例展示如何在这两个平台上创建一个简单的“Hello World”应用。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧,帮助你更好地理解和掌握移动应用开发。
40 17
|
2月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
110 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
3月前
|
监控 Android开发 iOS开发
深入探索安卓与iOS的系统架构差异:理解两大移动平台的技术根基在移动技术日新月异的今天,安卓和iOS作为市场上最为流行的两个操作系统,各自拥有独特的技术特性和庞大的用户基础。本文将深入探讨这两个平台的系统架构差异,揭示它们如何支撑起各自的生态系统,并影响着全球数亿用户的使用体验。
本文通过对比分析安卓和iOS的系统架构,揭示了这两个平台在设计理念、安全性、用户体验和技术生态上的根本区别。不同于常规的技术综述,本文以深入浅出的方式,带领读者理解这些差异是如何影响应用开发、用户选择和市场趋势的。通过梳理历史脉络和未来展望,本文旨在为开发者、用户以及行业分析师提供有价值的见解,帮助大家更好地把握移动技术发展的脉络。
112 6
|
3月前
|
开发工具 Android开发 iOS开发
安卓与iOS开发环境对比:选择适合你的平台
【9月更文挑战第26天】在移动应用开发的广阔天地中,安卓和iOS是两大巨头。它们各自拥有独特的优势和挑战,影响着开发者的选择和决策。本文将深入探讨这两个平台的开发环境,帮助你理解它们的核心差异,并指导你根据个人或项目需求做出明智的选择。无论你是初学者还是资深开发者,了解这些平台的异同都至关重要。让我们一起探索,找到最适合你的那片开发天地。
|
3月前
|
开发框架 Dart 前端开发
Android 跨平台方案对比之Flutter 和 React Native
本文对比了 Flutter 和 React Native 这两个跨平台移动应用开发框架。Flutter 使用 Dart 语言,提供接近原生的性能和丰富的组件库;React Native 则基于 JavaScript,具备庞大的社区支持和灵活性。两者各有优势,选择时需考虑团队技能和项目需求。
415 8
|
3月前
|
Android开发 开发者
Android平台无纸化同屏如何实现实时录像功能
Android平台无纸化同屏,如果需要本地录像的话,实现难度不大,只要复用之前开发的录像模块的就可以,对我们来说,同屏采集这块,只是数据源不同而已,如果是自采集的其他数据,我们一样可以编码录像。
|
3月前
|
安全 API 开发工具
Android平台RTMP推送|轻量级RTSP服务如何实现麦克风|扬声器声音采集切换
Android平台扬声器播放声音的采集,在无纸化同屏等场景下,意义很大,早期低版本的Android设备,是没法直接采集扬声器audio的(从Android 10开始支持),所以,如果需要采集扬声器audio,需要先做系统版本判断,添加相应的权限。
|
3月前
|
编解码 开发工具 Android开发
Android平台实现屏幕录制(屏幕投影)|音频播放采集|麦克风采集并推送RTMP或轻量级RTSP服务
Android平台屏幕采集、音频播放声音采集、麦克风采集编码打包推送到RTMP和轻量级RTSP服务的相关技术实现,做成高稳定低延迟的同屏系统,还需要有配套好的RTMP、RTSP直播播放器