在使用 Wireshare 或者 tcpdump 抓包时,往往面对 SSL/TLS 加密的数据报文束手无策。由于 SSL/TLS 的安全设计,防范了通讯双方以外的第三方截取数据后成功解析的可能。但也对开发测试过程中的抓包分析造成了不利影响。

获取数据有两类方案:

  1. 通过获取通信过程中的对称加密共享密钥,解析特定通信过程的数据包
  2. 通过在应用层挂载 Hook 获得并打印解密后数据内容

获取共享密钥

SSL/TLS 握手过程通过密钥交换算法协商共享密钥,并在通信过程中使用共享密钥,进行基于对称加密的通信。

协商的直接结果将使客户端与服务器分别得 pre_master_secret ,再加上 ClientHello / ServerHello 阶段的 client_randomserver_random ,客户端和服务端会使用一个 PRF(Pseudo-Random Function,伪随机算法)来产生 master-secret

$$ master_secret = PRF(pre_master_secret, client_random +server_random) $$

最后,在通信会话中使用的 shared secret ,是 master secret 在不同对称加密算法(握手过程中已提前协商)需要下做摘要算法的产物。

基于 RSA 密钥交换算法的 TLS 数据包解析

基于 RSA 密钥交换算法的协商过程:

  1. 由客户端生产 pre_master_secret ,被服务器证书携带的公钥加密
  2. 服务器接收后通过持有的私钥解密获得 pre_master_secret

这种方式下,通过获得服务器的私钥,整个通信过程的共享密钥将可以直接被计算得到。

在 Wireshark Preferences → Protocols → TLS 中编辑 RSA keys list,提供必要的私钥即可解析抓取的 TLS 数据包。

基于 Diffie-Hellman 密钥交换算法的 TLS 数据包解析

基于 Diffie-Hellman 密钥交换算法以数学理论做支撑,可以让通信双方在完全没有对方任何预先信息的条件下通过不安全信道协商一个密钥。

由于密钥交换过程不涉及公私钥,通过私钥解析 TLS 数据包已无法实现。

在整个流程中,只能退而求其次,由客户端或服务器记录下 TLS 握手时协商出的 pre_master_key ,以此解析当次 TLS 连接的通信内容。源于 NSS 的 Key Log File 提供了第三方解析 TLS 连接的能力。

通过配置环境变量 SSLKEYLOGFILE ,识别该环境变量的应用程序会将 pre_master_key 打印到指定文件。

# MacOS, for example
export SSLKEYLOGFILE=$HOME/keylogfile.txt
open -a firefox

最后,在 Wireshark Preferences → Protocols → TLS 中编辑 (Pre)-Master-Secret log filename,指向文件即可解析抓取的 TLS 数据包。

应用层挂载 HOOK

虽然 TLS 在通信过程中加密信息,让其下的 TCP, IP 层无法感知消息内容,但最终达到应用层的数据将是明文的。

程序以 DEBUG 形式打印消息

  • 诸如 Chrome 等浏览器,可以利用 DevTools 工具,向开发者呈现 HTTP(s) 的请求与响应内容。
  • 各编程语言涉及网络请求的,也可以自行利用 LOG 机制打印请求与响应,或者利用 DEBUG 工具断点查看
  • 或者想要不中断服务、不改写代码,也可以通过 uprobe 机制增强用户态动态共享库的方法,对解析方法挂载钩子打印消息内容。eCapture 就是这类工具的一个典型。

中间人攻击

理论上 TLS 只能确保通信过程的信息安全,如果出现第三者伪造服务器信息,代替真实的服务器构建了与客户端的连接,信息同样可以快速抓取并明文呈现。

通过将请求地址引导到 mintproxy 等代理软件,由代理软件将请求真实地发给第三方并透传响应结果,代理软件可以协助将消息内容进行打印。