![如何使用 RSA 异步加密通过 Wireshark 解密 TLS 流量?](https://linux22.com/image/756957/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%20RSA%20%E5%BC%82%E6%AD%A5%E5%8A%A0%E5%AF%86%E9%80%9A%E8%BF%87%20Wireshark%20%E8%A7%A3%E5%AF%86%20TLS%20%E6%B5%81%E9%87%8F%EF%BC%9F.png)
我希望能够捕获和解密我的内部应用程序(我无权访问)向互联网发出的 TLS 流量。(为了进行测试,我使用 Postman 创建对安全服务器的请求。)
我所做的是添加 Nginx 作为反向代理。
我使用以下命令创建了自签名证书:
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout localhost.key -out localhost.crt
我将 ssl 配置添加到 /etc/nginx/sites-enabled/default 文件证书中。
server { # SSL configuration # listen 443 ssl default_server; ssl_certificate /home/mavi/nginx/keys/localhost.crt; ssl_certificate_key /home/mavi/nginx/keys/localhost.key; ssl_protocols TLSv1.2 TLSv1.1 TLSv1; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. #try_files $uri $uri/ =404; proxy_pass https://myService.com; proxy_http_version 1.1; } }
我在 Wireshark 中添加了使用 OpenSSL 生成的密钥编辑 > 首选项 > SSL > RSA 密钥列表。
- 我创建指向我的代理(HTTPS://127.0.0.1)的请求,它将请求重定向到外部服务,我得到了正确的响应。
如果我使用 RSA 密钥交换,为什么我无法解密数据?
我一直在研究(如果我错了,请纠正我)异步加密的类型。我知道 RSA 将公钥及其证书发送给客户端,然后客户端使用此公钥加密数据。然后,当此加密数据发送到服务器时,它会使用私钥解密信息。所以如果我在 Wireshark 中使用此私钥,我应该能够解密数据,对吗?
此外,我读到,出于安全考虑,我们已停止使用 RSA,现在我们转而使用 Diffie Hellman 算法(ECDH、ECDHE DFH)。Diffie Hellman 及其变体不再使用私钥,而是使用保存在 RAM 中的随机会话密钥。(请注意,要解密 Diffie Hellman 包,我们需要在系统 $SSLKEYLOGFILE 中添加一个全局变量,并将此文件导入 Wireshark。这仅适用于 Google Chrome、Firefox、CURL,不适用于内部应用程序)
所以我认为这就是我无法解密数据的原因。因为在我的客户端和服务器(均在我的本地计算机中)的密码协商中,即使我创建了 RSA 证书,也使用 Diffie Hellman 作为异步加密。我猜他们正在使用 Diffie Hellman,因为在 TLS 握手中我看到他们同意使用 0xc030
如果我是对的,那么我应该将我的问题改为如何指定 Nginx 配置中使用的密码? 现在我的 Nginx 有 ssl_prefer_server_ciphers on; 配置。
我将添加 TLS 握手,以便您可以看到密码的协商。客户端您好
服务器问候
答案1
TLS 1.2 和 ECDHE-RSA-AES256-GCM-SHA384 具有前向保密性。请注意它在Mozilla 的密码列表. 无法仅使用服务器密钥进行解密。
提取客户端密钥。因为这会终止 nginx 上的 TLS,请获取 nginx 的客户端密钥。如果没有任何简单的选项可以启用此功能,请编译并加载您自己的钩子。例如,请参阅从 nginx 中提取 openssl 预主密钥利用某人的sslkeylog文件。因为 OpenSSL 的 keylog API 是已知的,所以这样的库适用于任何客户端,包括带有 OpenSSL 的 nginx。
与往常一样,在编译第三方代码时要小心安全和操作问题。如果 nginx 不是必需的,请考虑其他具有键盘记录功能的代理,例如mitmproxy
答案2
正如我猜测的那样,问题出在服务器和客户端同意的密码上。
只有使用 RSA 密钥加密数据,我们才能解密 TLS/SSL 数据包数据。如果使用 Diffie-Hellman Ephemeral (DHE) 或 RSA ephemeral 密码套件,则 RSA 密钥仅用于保护 DH 或 RSA 交换,而不会加密数据。因此,即使您拥有正确的 RSA 私钥,您也无法使用 ssldump、Wireshark 或任何其他工具解密数据。您可以通过检查持有私钥的主机发送的 Server Hello 数据包来检查正在使用哪个密码套件,如果指定的密码套件以 TLS_DHE 或 SSL_DHE 开头,您将无法解密数据。如果服务器发送 ServerKeyExchange 消息,您将无法解密数据。对于 DHE,您唯一的选择(如果可能)是修改客户端或服务器配置,以便不使用 DHE 密码套件。
ECDHE 或 DH (Diffie-Hellman) 均会创建只有参与 SSL 连接的实体才能访问的会话密钥。由于会话密钥未链接到服务器的密钥对,因此无法仅使用服务器的私钥来解密任何 SSL 会话。
所有 TLS_RSA 密码套件都被标记为 WEAK,因为它们不提供前向保密性,这意味着在 TLS_RSA 中私钥用于解密数据:如果私钥将来被泄露,则可以使用它解密所有记录的流量。
现在回答我自己的问题:如何指定 Nginx 配置中使用的密码?
我必须在 /etc/nginx/nginx.conf 文件中将 Nginx 服务器配置为仅使用 TLS_RSA 密码
http {
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
ssl_ciphers AES256-SHA256:AES256-SHA:AES128-SHA256:AES128-SHA:RC4-SHA:RC4-MD5:DES-CBC3-SHA;
}
这样我就能解密数据了。如下图所示,客户端和服务器同意使用 TLS_RSA_WITH_AES_256_CBC_SHA(0X0035),Wireshark 可以使用私钥解密数据。