ShokaX

非对称密码-使用私钥破解https流量

发布于 字数统计 4.4k 字 阅读时长 15 分钟

非对称密码-使用私钥破解https流量

发布于 字数统计 4,419 阅读时长 23 分钟

重温HTTPS

在开始之前,我们需要再次捋清整个HTTPS握手的流程,思考下面几个问题,你是否完全懂整个流程?


A:HTTPS中共用到了两种加密,这两种加密的作用和关系是什么?

Q:非对称加密只是为了加密对称加密的密钥(还起了身份认证功能),而对称加密用于加密真正的http数据。

A:非对称加密和对称加密的密钥分别是由谁形成的?

Q:首先,对称加密的密钥是由客户端来随机生成的。而非对称加密的密钥则需要考虑密钥协商算法了,在DHE/ECDHE等算法中,非对称加密的公私钥是临时生成的,私钥保存在服务端上,公钥则由服务端发送给客户端。而其他密钥协商算法如RSA、DH_DSS、DH_RSA等,则公钥使用的就是证书上的公钥。私钥就是服务端上证书的私钥。
A:证书在整个HTTPS过程中起了什么作用?

Q:在通常的HTTPS握手中,证书其实只是起到了认证的作用,浏览器通过预存的各大CA的公钥去解密证书的内容,判断目标是否为真实目标,而不是伪造的目标(也就是说,证书中的公私钥并不会用于后续的密钥协商)。当然对于RSA和DH密钥协商算法,证书的公钥就被用于加密预主密钥。
A:在私钥不泄露的前提下,客户端和服务端怎么保证对称加密的密钥不会被破解?

Q:首先我们需要知道公钥加密只能私钥解密,并且在HTTPS的过程中,服务端的私钥是不会返回给客户端的。
而这个对称加密的密钥是由客户端随机生成的,客户端使用服务端提供的公钥去加密这个私钥,返回给服务端。服务端接收后,再使用私钥去解密。因此在私钥不泄露的情况下,对称加密的密钥也自然不会被破解。
A:客户端和服务端怎么保证它们进行密钥协商交换后,大家得到的(对称)密钥是一致的。

Q:这里还是和上一个问题一样,在密钥交换过程中,客户端并非只是单单只把加密后的密钥发送给服务端。客户端和服务端都会在密钥协商完成后,将之前自己发过的包和收到的包做一个hash杂凑再用对称密钥进行加密发送给对方。
对方在接收到后,使用协商好的密钥去解密数据。一致则代表大家密钥协商成功,开始数据传输。

反复思考上面的几个问题,理解后我们不难得以下结论;

想要解密流量,要么获取非对称加密的私钥,要么获取对称加密的密钥。

  • 私钥是只在服务端上的,根据不同的密钥协商算法,这个私钥要么就是证书的私钥,要么是临时生成的保存在服务端缓存中的。
  • 对称加密的密钥即在客户端也在服务端上。但都只是在缓存中。

也就是说,我们破解流量就可以细分为以下几种场景:

①客户端权限:读取缓存中的加密密钥,一步到位。(部分使用openssl和nss库的应用可行)

②服务端权限:读取缓存中的对称加密密钥或者私钥(需要逆向服务器实现,工作量太大)再或者修修改服务器的首先密钥交换协议,使用我们或者它原本的证书私钥进行加解密。(优选)

③没有权限,只有流量包,和对应的私钥。直接使用私钥加解密。(得看密钥交换协议用的是临时的还是其他)

客户端权限

Chrome和Firefox会使用的NSS库来处理TLS。而NSS(OpenSSL也可以) 可以写入密钥日志,以便外部程序可以解密 TLS 连接。通过设置环境变量SSLKEYLOGFILE,将其指向一个可写入的文件。这样浏览器在启动时就会检查这个环境变量,如果存在的话,它会向指定的文件写入访问HTTPS站点时使用的密钥。我们只需要把这个文件给导入到wireshark,就可以解密流量了。

image-20220401152854695

image-20220401152859510

将该文件加载到wireshark中,waireshark就会自动解密,获取到HTTP流量

编辑->首选项->Protocols->TLS

image-20220401152913157

image-20220401152922277

导入sslkeylog后,流量成功破解。

image-20220401152926732

服务端权限(使用证书私钥直接解密)

服务端并不像客户端有浏览器输出sshkeylog,我们除非逆向服务器,不然密钥只出现在缓存中。

但是我们可以让服务器不走临时的密钥交换协议。

当然目前服务器默认都会选择ECDHE模式。因此我们要修改服务器选项,让服务器关闭临时交换算法来实现,这里用nginx服务器实现。

nginx配置SSL

检查环境是否支持SSL

nginx -V  #检查是否存在ssl模块,没有则需要重新build nginx

image-20220401153924002

生成自签名SSL证书

这里使用keytools生成自签名证书,再用openssl转换格式

image-20220401153950562

修改nginx配置文件,加载证书

在HTTP内新增一个server


 server {
        listen 80;
        listen 443 ssl;                # 监听443端口, 开启ssl(必须)
        server_name domain.com;
        ssl_certificate      /root/cer.crt;  #公钥(只能是文本格式的)
        ssl_certificate_key  /root/private.key; #私钥(也要文本格式)
        # 协议优化(可选,优化https协议,增强安全性)
        ssl_protocols        TLSv1 TLSv1.1 TLSv1.2;
#       ssl_ciphers          ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
#       ssl_prefer_server_ciphers  on;
#       ssl_session_cache    shared:SSL:10m;
#       ssl_session_timeout  10m;
         root /var/www/html;
 location / {
        index index.html index.htm;
       }
       
}

最终实现效果如下。

nginx -s reload

image-20220401154119525

修改服务器支持的加密套件

nginx中,ssl_ciphers配置项的可选值由openssl的ciphers定义

openssl ciphers  -v #输出当前服务器支持的加密套件,不加-v则是不换行输出。

image-20220401154315322

先获取当前服务器支持的套件,然后copy到vscode中,使用正则去掉所有的临时密钥交换算法

openssl ciphers #输出不换行的加密套件

(DHE|ECDHE)-[^:]{1,}: #VScode中去掉临时密钥交换算法的正则

image-20220401154457261

然后修改nginx的配置文件,添加ssl_ciphers 即可

image-20220401154503651

流量解密

这里已经很明了了,直接把服务器证书的私钥给导入wireshark就能读到明文数据了。

image-20220401154611626

image-20220401154618936

image-20220401154652128

nps流量解密

直接导入证书就完事了,在隧道传输流量的时候用的是TLS协议,和https是一样的

image-20220401160651917

image-20220401160702554