网络抓包原理
一. 什么是抓包?
在应用的开发调试中,查看软件实际运行时HTTP/HTTPS通信的请求数据和返回数据,从而分析问题的过程就叫做抓包。 通常我们说的抓包主要是分为两种:
- 使用 Wireshark 抓取传输层的 TCP/UDP 通信包。
- 使用 Fiddler 或 Charles 抓取应用层的 HTTP/HTTPS 通信包。
在大部分场景下,我们只是需要抓取应用层的
HTTP/HTTPS
数据包也就是第二种方式。
二. 抓包的原理
抓包的原理其实很简单,例如:PC上的Fiddler监听一个端口(port: 8888),在Android测试机上连接同一个局域网,配置网络代理,指向该PC的8888端口,这样一来测试机的所有网络通信都会被转发到PC的8888端口,进而被Fiddler捕获,然后就可以对数据包进行分析。经常用的网络协议分为HTTP和HTTPS,HTTPS在HTTP上进行了加密操作,所以对这两种请求进行抓包也有不同。
对HTTP请求进行抓包
对于HTTP协议,因为本身就是明文传输
,所以可以直接看到数据报文,除非对这些明文在传输时进行二次加密,但那是另一种情况,这里暂不分析。
对HTTPS请求进行抓包
对于双向加密的HTTPS,正常情况下,即使能以中间人的方式拿到通信报文
,但是因为没有密钥,同样也不能看到具体的传输内容。基于HTTPS加密通信的建立过程,和密钥交换方式,如果在加密通信建立之前,截取服务端发送的包含证书的报文,伪装成服务端,把自己的证书发给客户端,然后拿到客户端返回的包含对称加密通信密钥的报文,以服务端自己的公钥加密后发给服务端
,这样一来,双向加密通信建立完成,而中间人实际拿到了通信的密钥,所以可以查看、修改HTTPS的通信报文,这就是典型的Man-in-the-middle attack即MITM中间人攻击
。
这样似乎看起来,HTTPS也不是那么安全,当然不能这么说了,实现MITM最关键的一点,是中间人要把服务端证书替换成自己的证书发给客户端,让客户端相信自己就是服务端,那么问题是,客户端为什么会信任而进行替换呢?
HTTPS之所以安全,是因为它用来建立加密通信的证书是由权威的CA机构签发
的,受信的CA机构的根证书都会被内嵌在Windows, Linux, macOS, Android, iOS这些操作系统里,用来验证服务端发来的证书是否是由CA签发的。CA机构当然不可能随便给一个中间人签发不属于它的域名证书,那么只有一个很明显的办法了,把中间人的根证书,导入到客户端的操作系统里,以此来完成建立加密通信时对中间人证书的验证。
所以,在一定的情况下,HTTPS通信是可以被监听的,抓包的实现基础,是Android测试机导入Fiddler或者Charles的根证书。
无论是fidder和charles都是充当了一个中间人代理的角色来对HTTPS进行抓包:
- 截获客户端向发起的HTTPS请求,佯装客户端,向真实的服务器发起请求。
- 截获真实服务器的返回,佯装真实服务器,向客户端发送数据。
- 获取了用来加密服务器公钥的非对称秘钥和用来加密数据的对称秘钥。
如图:
三. Android设备抓包问题
Android6.0 及以下系统
直接安装证书后, 可以直接使用FIddler进行抓包。
Android7.0 及以上系统
在Android 7.0及以上的设备上测试时,发现又抓不到HTTPS了! 原因是:Google在Android 7.0时更改了App对操作系统本地证书的信任机制,在Android 7.0之前,默认信任系统预置证书和用户自导入证书,在Android 7.0(API 24)之后,为了保障App的通信安全,避免被第三方抓包做了些改动,App默认只信任系统预置证书,而不再信任用户自导入证书(把MITM的ssl证书,安装到 受信任的凭据 -> 用户)抓出来的https的请求,都是加了密的,无法看到原文了.解决的方式有如下几种:
- 方式一: 修改App的AndroidManifest网络安全配置,信任用户自导入证书。
- 方式二: Root测试机或自编译系统,把Fiddler根证书设置为系统预置证书。
- 方式三: 在Android 7.0以下的测试机中抓包。
- 方式四: targetSDK版本设置为24以下。
方式一:
如果是自己公司开发的应用那么在 Android 工程目录的 res 底下创建一个 xml 文件夹,然后在内部创建一个名为 “network_security_config.xml” 的文件。
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" overridePins="true" />
<certificates src="user" overridePins="true" />
</trust-anchors>
</base-config>
</network-security-config>
在 AndroidManifest 里的标签中,添加代码:
android:networkSecurityConfig="@xml/network_security_config"
这种方式只适用于能自己修改源码的应用。
方式二
root手机;Root手机将用户下载的CA协议移动到系统信任的证书目录下。
非root手机可以VirtualXposed插件:
- VirtualXposed 下载地址
- JustTrustMe 下载地址
PS: 方式三和方式四用的比较少·略
借鉴:
- 网络抓包原理及Fiddler的使用