tls1.3协议实战(二)----Encrypted Extentions
1、(1)上一篇tls1.3实战(https://www.cnblogs.com/theseventhson/p/14613527.html)分析了client hello和server hello,主要介绍了双方通过tls1.3协议握手的细节,还有一个很大的问题遗留:对于server hello包,wireshark就解析到了0xba这个位置(也就是ChangeCipherSpec),从0xbb到0x58e=1422的位置,还有1234byte并未解析,这些又都是什么数据了?纵观整个协议的握手过程,截至目前看到的都是handshake密钥交换阶段,record传输加密数据的阶段都在哪了?
ChangeCipherSpec字段本身是通知对方用协商好的对称密钥加密通信数据,所以从这之后的消息都是进行加密了的,可能是因为Wireshark没有对后续的消息进行解密,所以只是显示了ApplicationData,即加密传输的数据。
这些加密后的数据,那些时record阶段的数据了? record阶段的数据既然加密了,能解密查看么? 如果能,怎么查看了?
自己随便选个目录,比如我选了这个:D:\software\sslkeylog.log,在环境变量新建一个,取名为SSLKEYLOGFILE,如下:
然后在wireshark的编辑->首选项->Protocols选择TLS(网上有些教程是让选择SSL,但我用的是3.4.0版本,没有SSL选项,只有TLS选项),找到红框框的地方,添上刚才环境变量指定的log文件路径:
配置好后重新用chrome打开网页,sslkeylog.log文件内容:这个是tls1.2的内容,格式为:CLIENT_RANDOM <client_random> <master_secret>,也就是记录了client_random和master_secret;
CLIENT_RANDOM F6EC7D82E1A3704B9EEC4876FCAAB722E010D7FB4FA8DF332AF48D******** 2576E2B4C11802D86377C80B74504E7E03EDD11EE9CE780F86CB9DF06E30A1EC9FC15C14835252FE036DF7********
CLIENT_RANDOM 3DC71D07C9C3E512D7FFC5774BBCA8D07097580288BB3C86CA0E4F******** F6C87019AC A076F396E470C435DE478EDAEF9B2D6C72642706321A8A2456FD0A201A39D50EA055F6EA6EE0AEEFB********
至此,还未dump tls1.3的密钥到sslkeylogfile.log(文件除了几个CLIENT_RANDOM,就没其他内容了),所以wireshark还是无法解密record阶段的内容。网上查了很多资料,期间耗费了好几个小时,终于用这个命令成功把chrome的密钥dump到指定文件:
"C:\Program Files\Google\Chrome\Application\chrome.exe" --ssl-key-log-file=%SSLKEYLOGFILE%
文件都有61KB大了:
各种密钥收集了近700条:
wireshark也能正常解密了:能看到entrypt extension、certificate、verify、finished
至此:利用chrome dump的key在wireshark中成功解密tls1.3的数据!
(2)解密注意(这些坑耗费了我好几个小时排查):
- 环境变量设置好后,电脑不用重启,但浏览器要重启;
- 在任务管理器看看浏览器进程是不是全部退出,不能有任何残留的实例;如果不确定,建议重启电脑,确保浏览器进程全部退出,没有残留
- 执行如下的命令:给浏览器认为设置一个参数;(直接打开浏览器是没用的!一定要手动给浏览器设置这个参数!)
"C:\Program Files\Google\Chrome\Application\chrome.exe" --ssl-key-log-file=%SSLKEYLOGFILE%
(3)上面都是现象,原理在这:这里用的是ECDHE算法让双方互相交换公钥,然后各自根据曲线类型和对方的公钥生成对称加密的密钥pre-master-secret。这个对称密钥并未通过网络传输,所以wireshark是抓不到的!怎么才能得到这个密钥了?就是通过上述设置环境变量的方式,让浏览器把pre-master-secret导出到指定的log文件,然后wireshark去指定的文件读密钥,就能解密application data了!
2、接下来介绍一下这几个重点的handshake protocol;
- handshake protocol:certificate;client和server在通信时,为了确认发数据人的身份,就需要认证。这里server会先把证书发给client,client用事先内置的第三方权威认证中心的公钥解密证书,来确认这个证书是不是server发过的(紧接着下一个certificates verify字段就是干这个的)!这两个证书就是google发给client的证书。证书里面有google生成的ECC的公钥,用于和client协商生成对称加密的密钥;既然是证书,包含的内容有很多,两个证书一共有3532byte;
证书中比较重要的字段:
1) issuer:这个证书的颁发者
2)validity:证书有效期
3)subject:这个证书颁发给谁的,这里明显是google;
4)subjectPublicKeyInfo:server的公钥信息。这里能看出来采用了secp256r1曲线,并提供了server的公钥给client;后续client会根据这个公钥生成对称密钥;
- handshake Protocol:certificate verify;这里选用的是secp256r1椭圆曲线来做认证,确保服务器发过来的certificates是没有被篡改的;certificate的hash值是用sha256计算出来的,长71byte;
- handkshake Protocol:Finished;Finished消息是身份验证阶段的最后一条消息,也是第一个使用协商的算法簇进行加密和防篡改保护的消息;Verify Data是通过HMAC计算得来的,包含finished_key和握手消息的hash。 verify_data =HMAC(finished_key,Transcript-Hash(Handshake Context,Certificate, CertificateVerify))
3、 至此,所有的application data都被解密,并还原成了http包:
随便打开一个http包,所有的head信息都能看到:
4、最后做个总结:tls1.3中双方握手通信的流程图如下:
- +表示该报文中值得注意的extension
- * 表示该内容也可能不被发送
- {} 表示该内容使用handshake_key加密
- [] 表示该内容使用application_key加密
其中:(1)handshake_key是由我们使用的PSK与前两次报文,使用HKDF(内建的某函数,其中会使用到加密套件指定的哈希算法)导出而来的
(2)application_key则是以整个握手阶段的报文作为输入,计算四次HKDF导出而来
补充:刚开始学这些通信协议的时候会遇到各种证书,不太能分得清,这里系统性总结一下:
(1)根证书:由全球权威机构颁发,在浏览器或操作系统出厂时就内置好的(当然证书是可以增加的,如fiddler的证书);chorome查询如下:
根证书核心的功能之一是提供公钥,作为信任链建立的起点!证书内容如下:
(2)中间机构颁发机构:由根证书机构签发的,可直接用户签发网站的证书!这里的证书也是可以添加的,比如fiddler;内容和根证书一样!
(3)个人证书:这里面都是fiddler为了抓包而颁发的,目的是欺骗客户端!
从上面的截图可以看到,为了作为中间人抓包,fiddler在3个地方都安装了证书,这些证书都是怎么工作的了? 为什么安装了证书的fiddler就能解密https这些加密的数据包了?
- 首先:fiddler要求用户把自己的证书安装在受信任的根证书颁发机构,fiddler证书就成了CA根证书;
- 其次:再用这个CA根证书给自己颁发中间证书;最后再用这个中间证书伪造各个网站的证书;
- 最后:一旦拦截客户端的访问请求,就把伪造的这些网站证书发给客户端,让客户端误以为fiddler就是目标网站,达到欺骗的目的!具体做法就是fiddler在伪造的个人证书中内置自己的公钥,后续客户端会利用这个公钥、根据tls1.3协议生成各种premaster key、session key等,fiddler截获后可以直接解密数据了!在客户端看来,以为通信的对方就是网站,其实是fiddler!罪恶之源就是CA根证书被更改,导致整个信任链建立的起点被篡改!
参考:
1、https://gohalo.me/post/decrypt-tls-ssl-with-wireshark.html 使用 Wireshark 解密 SSL/TLS 流量
2、https://strawberrytree.top/blog/2020/09/17/%E4%BD%BF%E7%94%A8openssl%E4%BD%BF%E7%94%A8%E5%A4%96%E9%83%A8psk%E8%BF%9B%E8%A1%8C%E6%8F%A1%E6%89%8B%EF%BC%88tls1-3%EF%BC%89/ 使用OpenSSL指定加密套件使用外部PSK进行握手(TLS1.3,OpenSSL3.0)
3、https://zh.wikipedia.org/wiki/%E6%A0%B9%E8%AF%81%E4%B9%A6 根证书