我可以从 HTTP 客户端获取 TLS 机密来解密我自己的 HTTPS 对话吗?

Posted

技术标签:

【中文标题】我可以从 HTTP 客户端获取 TLS 机密来解密我自己的 HTTPS 对话吗?【英文标题】:Can I obtain TLS secrets from an HTTP client to decrypt my own HTTPS conversation? 【发布时间】:2017-08-22 23:44:00 【问题描述】:

我正在构建一个类似于代理的网站记录器,以便持续测试网络爬虫。它分为三个 Docker 容器,均在 GNU/Linux 上:(1) 一个代理,(2) 一个 API 和请求队列,以及 (3) 一个简单的 Web 应用程序。

它适用于 HTTP 站点:我单击 Web 应用程序中的一个按钮,这会向 API 容器发出请求,并将某些内容添加到内部请求队列中,然后该队列通过代理请求站点。代理会在站点经过时记录站点。

但是,我忘记了不能记录 HTTPS 站点流量,现在我来实现这一点,我发现代理只是使用 CONNECT 动词,然后充当服务器之间的数据交换器客户和目标。我相信我无法重放相同的数据块,因为加密的一部分使用随机的、一次性的对称密钥(但是我有一个适合测试它的脚本,所以我这样做只是为了教育价值!)。

所以,我想知道我的获取客户端是否可以为代理系统放弃足够的秘密来解码字节流?我正在使用 Wget 进行提取,我猜这将使用 OpenSSL。但它不需要是 Wget:如果我使用带有流上下文的 file_get_contentsphp 脚本,我可以向 openssl module 询问解密密钥吗?

(说句公道话,即使可能,我也可能不会以这种方式解决问题,我只是觉得多了解一下TLS会很有趣。在实践中,我会记录一个“null”访问代理中的所有安全网站,并要求请求服务通过 API 调用通知代理头/正文数据,以便稍后回放。他们当然会有这些项目的明文副本)。

【问题讨论】:

如果可以的话,我会非常担心。 为什么是@miken32?出于大多数实际目的,加密是牢不可破的,因为客户端不会将秘密发送给想要它们的破解者。但是,在一个封闭的系统中,如果可以要求它在获得许可的情况下放弃这些秘密,那肯定可以用于解密,而不必担心加密系统普遍存在缺陷吗? 我添加了一个赏金,以诱使人们回答。这是一个没有真正目的的有趣问题,但我认为这很有趣。如果这是可能的,我希望答案会说必须编写/修改自己的客户端,以便能够从 OpenSSL 中找出必要的秘密。当然,我不是在寻找工作代码,因为那会相当广泛 - 只是涉及的技术。 OpenSSL 是否允许客户端在不重新编译 OpenSSL 的情况下获取所有机密? 顺便说一句,如果这是用于商业项目,我建议使用现有的 HTTPS 调试代理之一来执行此操作,而不是尝试自己编写。我知道至少 fiddlerbook.com/fiddler/help/httpsdecryption.asp 和 charlesproxy.com/documentation/proxying/ssl-proxying 就是这样做的,包括 TLS 展开。如果这是一个爱好或教育项目来了解 HTTPS,那么请继续努力! 好建议,谢谢@Rich。目的是用于商业项目,但它只是用于测试而不是生产,并且无论如何我通过在客户端中修改它们并稍后在代理中更正来避免需要在代理中处理 TLS 连接。我确实尝试了一个现成的解决方案(Wiremock),但它没有按我的预期工作,我不得不退出一些工作。至少如果我写了,我可以修改它:-) 【参考方案1】:

是的,我认为您在这里有几个选择。

HTTPS 专门设计用于阻止"Man in the Middle" attacks 和窃听者,这基本上是您想要实现的目标。不过你可以打破它的一些假设,然后打败它。

在 SSL 连接开始时,1. 远程服务器提供其公钥和证书,2. 客户端验证证书并 3. 发送使用服务器公钥加密的会话密钥。有关更多详细信息,请参见例如An overview of the SSL or TLS handshake

在您描述的场景中,您有两种可能的方法来规避这种保护:

1。重写 TLS 数据,用你自己的替换服务器的证书和密钥

由于您控制了通信通道,因此您可以在步骤 (1) 中用您控制的公钥和证书替换服务器的公钥和证书。如果您使用wget--no-check-certificate 参数要求客户端跳过步骤(2),那么您就可以完全访问加密数据。

这是 Fiddler 调试代理允许访问 HTTPS 流量的方式,请参阅https://www.fiddlerbook.com/fiddler/help/httpsdecryption.asp

2。从客户端应用程序检索会话密钥

由于客户端应用知道会话密钥,如果您可以提取它,您就可以解密流。我认为这就是您在问题中的想法。

wget 本身没有允许记录会话密钥的选项(请参阅“HTTPS (SSL/TLS) Options”),但它确实看起来像它的 TLS 库,“GnuTLS”有一个调试选项,可以满足您的要求,见"Debugging and auditing" in the GnuTLS docs:

SSLKEYLOGFILE 当设置为文件名时,GnuTLS 将在其上附加 NSS 密钥日志格式的会话密钥。该格式可以被wireshark读取,并允许解密会话以进行调试。

尝试将SSLKEYLOGFILE 环境变量设置为文件名,看看wget 是否会将您的TLS 会话密钥记录到该文件中?您可能需要使用GnuTLS 的调试版本重新编译wget。我自己没试过。

【讨论】:

太好了,2 号看起来非常接近我的想法,但 1 号非常有趣 - 谢谢!我需要在这里阅读...

以上是关于我可以从 HTTP 客户端获取 TLS 机密来解密我自己的 HTTPS 对话吗?的主要内容,如果未能解决你的问题,请参考以下文章

SSL和TLS协议如何提供身份验证机密性和完整性

HTTPS -- TLS

HTTPS -- TLS

在https的网站里不小心嵌套了http的网址会发生什么?

SSL/TLS通信

如何在没有 SSL/TLS 的情况下加密数据客户端并在另一个客户端解密?