最近有读者问了一个奇怪的事情。他说,他想捕捉一个来自Baidu com的数据包,并体验看它的乐趣。但奇怪的是发现“我抓不住”。我来还原一下
最近有读者问了一个奇怪的事情。他说,他想捕捉一个来自Baidu.com的数据包,并体验看它的乐趣。
但奇怪的是发现“我抓不住”。
我来还原一下他的操作步骤。
首先通过ping命令,获取访问百度时会请求哪个IP。
$ ping Baidu . compingbaidu . com(39 . 156 . 66 . 10)56(84)bytes ofdata . 64 bytes from 39 . 156 . 66 . 10(39 . 156 . 66 . 10):icmp _ seq=1ttl=49 time=30.6 ms 64 bytes from 39.156.66.10(39 . 156 . 66 . 10):icmp _ seq=2ttl=49 time=30.6 ms 64 bytes from 39.156.66.10(39
所以用下面的tcpdump命令来抓包,大概意思是用eth0网卡和39.156.66.10 IP来抓包,保存在baidu.pcap文件中。
$ tcpdump-ieth 0 host 39 . 156 . 66 . 10-wbaidu . pcap在浏览器中打开wbaidu.pcap网页。或者在另一个命令行窗口中,直接使用curl命令进行模拟。
$curl'https://baidu.com '按理说,访问baidu.com的数据包肯定被抓了。
那就别抢包了。
用wireshark打开baidu.pcap文件,在filter列输入http.host=='baidu.com '
这时,我什么也没发现。
在wireshark搜索百度的包,一无所获。为什么?
在这里,有经验的朋友其实都知道问题出在哪里。
他为什么没有抓住包裹?实际上,那是因为他参观了HTTPS Baidu.com议定书。HTTP协议中的主机和实际发送的请求体都将被加密。
因为是加密的,所以没有办法通过http.host过滤
但是.
虽然加密了,但如果你愿意还是可以屏蔽的。
在HTTPS握手的客户端Hello阶段,有一个扩展server_name,它会记录你要访问哪个网站,可以通过以下过滤条件过滤掉。
Tls . handshake . extensions _ server_name==' Baidu . com '可以通过TLS的扩展server _ name搜索百度的包。此时选择其中一个包,右键单击并选择Follow-TCP Stream。
右键找到tcp流,可以显示该TCP连接的所有其他相关消息。
从截图中可以看出,HTTPS抓包完整的经历了TCP握手和TLS加密握手过程,之后是两次加密报文和TCP挥舞过程。
可以看到,数据包18和20,一个是从端口56028发送到443,另一个是从443返回到56028的数据包。
一般来说,像56028这样比较大且不规则的数字,是客户端随机生成的端口号。
443是HTTPS的服务器端口号。
HTTP使用80端口,如果此时在80端口抓取数据包,将无法抓取数据。
粗略地说,包18和20分别是请求Baidu.com的客户端的请求包和响应包。
点进去会发现URL和body都加密了,什么都没发现。
那么问题来了。有没有办法解密里面的数据?
有一个办法。我们来看看怎么做。
首先解密数据包或执行tcpdump数据包抓取。
$ tcpdump-ieth 0 host 39 . 156 . 66 . 10-wbaidu . pcap然后在另一个命令行窗口中执行下面的命令,目的是导出加密的密钥,并给出相应的导出地址作为/Users/Users/xiaobaidebug/SSL . key
$ exportslkeylogfile=/users/xiaobaidebug/SSL . key然后在同一个命令行窗口中,继续执行curl命令或者用命令行打开chrome浏览器。目的是让curl或者chrome继承这个环境变量。
$curl'https://baidu.com '或$open-aGooglechrome#在mac上打开chrome浏览器,你会在/Users/xiaobaidebug/下看到一个额外的ssl.key文件。
此时,按照以下操作修改wireshark的配置项。
打开wireshark的配置项并找到协议后,用力向下滚动并找到TLS项。
在配置项中找到协议,并将导出的ssl.key文件路径输入到该标题中。
在协议中找到TLS列并单击OK后,您可以看到数据包18和20已被解密。
此时可以使用http.host=='baidu.com '过滤掉解密的包内容。
百度的包可以从解密的包中过滤出来,但是看不到包的问题解决了。
然而,新的问题又来了。
什么是ssl.key文件?
这就要从HTTPS的加密原理说起。
HTTPS握手过程HTTPS握手过程比较复杂,我们来回顾一下。
首先,建立一个TCP连接。毕竟HTTP是基于TCP的应用层协议。
TCP成功建立协议后,可以开始进入HTTPS阶段。
HTTPS可以用TLS或SSL加密。我们以TLS1.2为例。
总的来说。整个加密过程实际上分为两个阶段。
第一阶段是TLS四次握手,主要是利用非对称加密的特性来交换信息,最后得到一个‘会话密钥’。
第二阶段是基于第一阶段中的“会话密钥”进行对称加密通信。
TLS四次握手我们先来看看TLS四次握手的第一阶段。
第一次握手:
客户端Hello:客户端告诉服务器它支持什么加密协议版本,比如TLS1.2,它使用什么加密套件,比如最常用的RSA,还会给一个客户端随机数。
第二次握手:
ServerHello:服务器告诉客户端,服务器随机选择由服务器证书决定的加密协议版本(例如TLS1.2)。
第一次三次握手:
客户端密钥交换:此时,客户端生成一个名为pre_master_key的随机数。从第二次握手的服务器证书中取出服务器公钥,用公钥加密pre_master_key并发送给服务器。
更改密码规范:客户端已经有三个随机数:客户端随机数、服务器随机数和pre_master_key。使用这三个随机数计算并获得一个“会话密钥”。此时,客户端通知服务器该会话密钥将在以后用于对称机密通信。
加密握手消息:客户端将生成到目前为止的通信数据内容摘要,用“会话密钥”对其进行加密,并将其发送到服务器进行验证。此时客户端的握手过程已经结束,所以也叫完成消息。
第四次握手:
Change Cipher Spec:此时服务器从客户端获取pre_master_key(虽然是用服务器的公钥加密的,但是服务器有私钥,可以解密得到原文),收集三个随机数,用这三个随机数通过和客户端相同的算法得到一个‘会话密钥’。此时,服务器告诉客户端这个“会话密钥”将在以后用于加密通信。
加密握手消息:与客户端的操作一样,生成到目前为止的通信数据内容的摘要,用“会话密钥”加密,并发送给客户端进行验证。此时,服务器的握手过程就结束了,所以这也叫完成消息。
在四次握手中,客户端和服务器端都以三个随机数结束,这三个随机数非常重要,我特意加粗。
第一次握手会生成一个名为client random的客户端随机数。
第二次握手的时候,服务器也会生成一个服务器随机数,叫做server random。
在三次握手中,客户端还会生成一个名为pre_master_key的随机数。
这三个随机数一起构成了最终的对称加密密钥,也就是上面提到的“会话密钥”。
三个随机数生成一个对称密钥。你可以简单地认为,只要知道这三个随机数,就可以破解HTTPS通信。
这三个随机数中,客户端随机和服务器随机都是明文,大家都可以知道。但是pre_master_key不行。它是用服务器的公钥加密的,只有客户端和拥有相应服务器私钥的人才能知道。
所以问题就变成了,我怎么才能得到这个pre_master_key?
如何获得pre_master_key服务器私钥并不是每个人都可以获得的,那么问题就变成了,有没有办法从客户端获得这个pre_master_key?
是的。
当客户端使用HTTPS与服务器端传输数据时,需要先建立一个基于TCP的HTTP连接,然后才能调用客户端的TLS库(OpenSSL,NSS)。触发TLS四次握手。
此时,如果添加环境变量SSLKEYLOGFILE,就可以干扰TLS库的行为,让它输出一个包含pre_master_key的文件。这个文件就是我们上面提到的/Users/xiaobaidebug/ssl.key。
在curl和chrome中注入环境变量,但是虽然TLS库支持导出关键文件。但前提是上层应用调用TLS库时,支持触发TLS库通过SSLKEYLOGFILE环境导出文件。事实上,并不是所有的应用程序都支持SSLKEYLOGFILE。目前只支持常见的curl和chrome浏览器。
SSLKEYLOGFILE文件的内容让我们回头看看ssl.key文件的内容。
#SSL/TLSsecretslogfile,generated byssclient _ random 5709 AEF 8 ba 36 A8 EAC 72 BD 6 f 970 a 74 f 7533172 c 52 be 41 b 200 ca 9 b 91354 BD 662 b 09d 156 a5 E6 c0d 246549 f 6265 e 73 BDA 72 f 0 D6 ee 81032 eaaa 0 BAC 9 bea 36209 0800174 E0 effc 93 b 93 c
第一列是CLIENT_RANDOM,也就是说第二列是客户端随机数,第三列是pre_master_key。
但是问题又来了。
这么多行,wireshark怎么知道用pre_master_key的哪一行?
Wireshark可以随机获取客户端的数据消息。
比如如下图。
客户端Hello中的客户端随机数注意,上面的客户端随机数以‘BFF 63 bb 5’结尾。
类似地,您可以在数据消息中获得server random。
找到server random,把client random放在ssl.key的第二列,一一匹配。
你可以找到相应的记录行。
注意ssl.key中数据第二列的字符串,也是以' bff63bbe5 '结尾的,其实就是前面提到的client random。
然后把这一行第三列的数据拿出来,就是我们想要的pre_master_key。
那么这个时候wireshark已经收集了三个随机数,这个时候就可以计算出会话密钥,用来解密数据了。
反之,正是因为需要客户端随机数,才能定位到ssl.key文件中对应的pre_master_key。这个随机数只有在TLS第一次握手(客户端hello)时才可用,所以如果要用解密HTTPS包,必须掌握TLS的四次握手,才能解密。如果连接已经建立,数据已经发回很久了,这个时候再抢包就没办法解密了。
总结文章开头通过抓取百度的数据包,展示了用wireshark抓取数据包的简单操作过程。
HTTPS会对HTTP的URL和请求体进行加密,所以直接在过滤栏http.host=='baidu.com '中过滤将一无所获。
在HTTPS握手的过程中,会通过非对称秘密交换各种信息,包括三个随机数,然后通过这三个随机数生成对称秘密的会话密钥,再用会话密钥进行对称加密通信。如果我们能得到这三个随机数,我们就能解密HTTPS的加密数据包。
三个随机数是客户端随机数、服务器随机数和pre_master_key。前两个是明文,第三个是服务器公钥加密的,需要在客户端通过SSLKEYLOGFILE导出。
通过设置SSLKEYLOGFILE环境变量,curl或chrome将请求HTTPS域名,这将使它们在调用TLS库的同时导出相应的sslkey文件。该文件包含三列,其中最重要的是第二列中的客户机随机信息和第三列中的pre_master_key。第二列client random用于定位,第三列pre_master_key用于解密。
审核编辑:李倩
声明本站所有作品图文均由用户自行上传分享,仅供网友学习交流。若您的权利被侵害,请联系我们