从http到https,无疑是安全性上很大的一次升级,我们想搞清楚https抓包的原理,我们可首先回顾一下http到https的过程。
http 抓包
由于http明文的特性,我们可以非常容易的获取到http的请求内容,我们可以为请求指定一个proxy,甚至在是把截取程序直接路由器等设备中,可以轻松的获取拿到http的内容。
我们使用最著名的网络协议分析工具Wireshark进行分析。在访问http://www.baidu.com
后可以轻松的截获http的明文内容。
https的改进
由于http裸奔的缺陷,https(http secure)使用了多个加密协议对http进行通讯加密,保证了数据内容的安全性,并一定程度上阻挡了中间人攻击。https通讯的整个过程还是比较复杂的,我这里就以最常见的TSL1.2版本协议为例,大致分为以下几步。
-
客户端发起https通讯ClientHello,包括支持的加密套件、key_share携带一个
client random
等信息。 -
服务端接收到之后,会做出响应ServerHello,分批次发送
server random
、证书、公钥
、支持的加密套件、支持的加密协议版本等信息。 -
证书校验与预加密
-
客户端在接受到serverHello之后需要校验证书(当然你也可以主动选择跳过)证书如果是通过证书授权机构签章的,那么你不需要安装任何认证授权(Certificate Authority),你的手机电脑里自带的CA将会识别出证书的真伪,以此来防止中间人攻击。
-
客户端客户端会从服务端支持的加密套件和协议中挑选一个自己适配的。
-
客户端产生一个
pre master sercret
并使用服务端发的公钥进行加密。 -
将加密的
pre master sercret
以及最终敲定的加密套件发送给服务端。
-
-
服务端接受到加密后的
pre master sercret
后使用自己的私钥对其进行解密。这时这是服务端和客户端同时拥有了三组随机数 `client random、server random、pre master sercret,然后告诉客户端,已经可以进行加密通讯了。 -
之后客户端用与服务端都可以使用敲定的加密算法对
client random、server random、pre master sercret
进行加密生成master secret
,用master secret
进行对称加密通讯即可。
协议具体细节可以看这里🔗
我们在使用抓取访问https://www.baidu.com
的请求内容可以发现。进过https握手之后,数据变成了不可读的加密数据(下图encrypted Application data)。
中间人攻击
我们知道https是端到端的加密,我们无法像http代理那样中途获取并查看数据流的内容。那么我们如何才能抓取到数据呢?我们可以使用中间人攻击技术(man-in-the-middle 简称 MITM)。 在https的那一part,我讲到客户端需要对证书进行校验,这可以防止中间人攻击。那么如何解决证书校验的问题呢?其实我们可以伪造一个相同特征的证书,这个证书使用中间人的CA私钥进行签名,然后将CA公钥安装到Client上(当然第三方证书的安装并不容易,需要操作系统进行用户授权,让用户知道自己在进行危险操作),用中间人CA公钥进行验签,这样就骗过了客户端自己就是服务端。由于服务端不会验证客户端的真伪,中间人只需要伪装成一个客户端进行访问即可。
实际上整个过程会更复杂一些,我们使用图解来进行详细过程的描述。
- 客户端发起一个 HTTP CONNECT 请求
- 中间人进行响应,让客户端感觉好像和服务端连接上了。
- 客户端相信自己已经和服务端呼应上了,然后开始发起TLS连接,并且携带SNI(作用是告诉服务端需要那个host的证书)
- 中间人仿冒了客户端的请求内容,和服务器进行SSL连接
- 服务器返回匹配的证书,这其中包含CN和SANs(相当于证书支持的域名,用户客户端检查服务端返回的域名是否可用),我们根据返回的证书信息仿造一个相似的证书。
- 使用仿造的信息对step3进行回应
- 客户端发送TLS建立完成的请求
- 中间人发送TLS建立完成的请求
抓包工具
目前市面上有很多工具可以使用,老派的桌面工具有fidller,charles,性能稍差,但是安装容易。熟悉js也可以使用国人开发的whistle。我个人比较喜欢基于python的mitmproxy。 这里使用mitmproxy,进行证书配置后,就可以抓到https的内容了。
我们对比证书可以发现,实际服务端证书签发者从GlobalSign,变成了mitmproxy,这也是https抓包最核心的一步。