0x01 HTTPS协议

HTTPS协议本质上是HTTP协议+TLS/SSL协议,http工作在应用层,应用层把明文的数据转给工作在传输层的TLS/SSL,由TLS/SSL加密后再送往TCP套接字。

2016101509260864.jpg
下面通过wireshark抓包详细了解TLS协议工作原理。

0x02 TLS协议

1、TCP三次握手
客户端与服务端进行TCP三次握手
DeepinScrot-2119.png
2、客户端发送client hello
消息中主要包含(1) 按优先顺序列出的客户端支持tls/ssl版本
DeepinScrot-4439.png
(2) 客户端随机数
DeepinScrot-0424.png
(3) 按优先顺序显示的Cipher suite密码套件
DeepinScrot-0524.png
3、服务器端发送server hello
消息中主要包含(1) 确定加密的tls/ssl版本
DeepinScrot-2618.png
(2) 服务器端随机数
DeepinScrot-2700.png
(3)从客户端列出的密码套件中选出的一个密码套件
DeepinScrot-2756.png
4、服务器端发送Certificate
服务器按信任链的顺序发送完整的证书列表。该链中的第一个是服务器证书,接着是颁发服务器证书的intermediate CA 的证书,然后是下一个intermediate CA 的证书......直到Root CA的证书。服务器不可以发送Root CA证书,因为在大多数情况下,浏览器可以从任何intermediate CA 识别Root CA。证书主要用于身份验证与密钥交换,身份验证包括证书的颁发机构,过期时间,第三方证书认证机构(CA)的签名,服务端的域名信息等,密钥交换指的是证书包含后续加密过程中使用的公钥Subject Public Key Info。
DeepinScrot-2815.png
下图中,第一个证书为baidu.com,第二个证书则为GlobalSign Organization Validation的证书
DeepinScrot-5237.png
浏览器接收到服务器发送的证书后也可以进行查看
DeepinScrot-5727.png
5、服务器端发送Server Key Exchange
服务器密钥交换消息不是必须的,仅用于证书(服务器)消息没有包含足够的信息来建立预置密钥。因为服务器选择的加密套件为TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,这意味着双方使用Elliptic Curve Diffie Hellman算法来交换密钥,而证书中不带该Diffie-Hellman公钥,所以需要单独发送Server Key Exchange来传递Diffie-Hellman公钥。
DeepinScrot-1404.png
6、服务器端发送Server Hello Done
服务器通知客户端 server_hello 信息发送结束
DeepinScrot-1701.png
7、客户端发送Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
DeepinScrot-2508.png
客户端发送Client Key Exchange消息,其中包含有由客户端创建的预主密钥。
预主密钥(Pre-Master Secret)计算取决于商定的密钥交换算法的类型。当使用RSA进行密钥交换时,从客户端(即浏览器)计算预主密钥,客户端通过连接协议版本(2个字节)和客户端随机生成的一些字节(46个字节)来生成48字节的预主密钥。客户端从加密安全的伪随机数发生器(PRNG)获得这46个字节。实际上,这意味着使用操作系统提供的PRNG,例如/dev/urandom。然后,使用服务器下发的公钥对此Pre-Master密钥进行加密,之后再通过client key exchage发送给服务器。如下图所示,C即是预主密钥,服务器收到预主密钥后利用自身的私钥即可解密得到S。
20170919085048489.png
但是我们的例子使用ECDHE算法用于密钥交换,所以情况略有不同,服务器立即生成一对DH私钥 - 公钥。然后,与客户共享公钥。这是如上所述的"服务器密钥交换消息( Server Key Exchange)"。作为响应,客户端还将创建DH私钥 - 公钥,并通过客户端密钥交换消息与服务器共享公钥。
DeepinScrot-2316.png
ECDHE算法如下图,椭圆曲线名和Pb通过server key exchange报文发送;Pa通过client key exchange报文发送。使用Diffie Hellman算法进行TLS密钥交换具有优势。客户端和服务器都为每个新会话生成一个新密钥对。一旦计算出预主密钥,将立即删除客户端和服务器的私钥。这意味着私钥永远不会被窃取,确保完美的前向保密。
20170919085244124.png
客户端发送Change Cipher Spec消息,通知服务器之后会以加密的方式发送数据。
客户端发送Encrypted Handshake Message,这一步对应的是 Client Finish 消息,客户端将前面的握手消息生成摘要再用协商好的密钥加密,这是客户端发出的第一条加密消息。服务端接收后会用密钥解密,能解出来说明前面协商出来的密钥是一致的。
8、服务器发送Change Cipher Spec消息
这一步是服务端通知客户端后面再发送的消息都会使用加密,也是一条事件消息。
DeepinScrot-0854.png
9、服务器发送Encrypted Handshake Message消息
这一步对应的是 Server Finish 消息,服务端也会将握手过程的消息生成摘要再用密钥加密,这是服务端发出的第一条加密消息。客户端接收后会用密钥解密,能解出来说明协商的密钥是一致的。
10、双方开始发送Application Data
到这里,双方已安全地协商出了同一份密钥,所有的应用层数据都会用这个密钥加密后再通过 TCP 进行可靠传输。
DeepinScrot-1716.png

0x03 会话缓存握手

为了加快建立握手的速度,减少协议带来的性能降低和资源消耗(具体分析在后文),TLS 协议有两类会话缓存机制:会话标识 session ID 与会话记录 session ticket。
session ID 由服务器端支持,协议中的标准字段,因此基本所有服务器都支持,服务器端保存会话ID以及协商的通信信息,Nginx 中1M 内存约可以保存4000个 session ID 机器相关信息,占用服务器资源较多;
session ticket 需要服务器和客户端都支持,属于一个扩展字段,支持范围约60%(无可靠统计与来源),将协商的通信信息加密之后发送给客户端保存,密钥只有服务器知道,占用服务器资源很少。
二者对比,主要是保存协商信息的位置与方式不同,类似与 http 中的 session 与 cookie。
二者都存在的情况下,(nginx 实现)优先使用 session_ticket。
握手过程如下图:
20160908114052187.png
下面对session ID机制的情况进行分析:
1、客户端与服务器进行tcp三次握手
DeepinScrot-5008.png
2、客户端发送client hello
client hello中包含上一次握手成功的session ID,服务器将根据收到的 session ID 检索缓存记录,如果没有检索到货缓存过期,则按照正常的握手过程进行
DeepinScrot-1509.png
3、服务器发送server hello
4、服务器发送change cipher spec
服务器表明后面发送的消息都会使用加密
5、服务器发送encrypted handshake message
encrypted_handshake_message 是到当前的通信参数与 master_secret的hash值,发送给客户端验证其是否能正确解密。
DeepinScrot-2025.png
6、客户端发送Change Cipher Spec, Encrypted Handshake Message
与服务器端发送的类似,表明从下一个消息开始使用加密,而Encrypted handshake message便是使用对称密钥加密的第一个消息。
DeepinScrot-3223.png
7、双方开始发送application data

0x04 HTTPS协议解密

密钥交换算法有两种:1、RSA算法 2、Diffie-Hellman算法,也就决定了解密也是针对这两种算法想办法。
1、RSA算法
RSA算法可导入服务器私钥,获取到服务器私钥,便可利用客户端向服务器端发送的Client Key Exchange里的预主密钥,再配合random client和random server两个随机数解密出对应的主密钥,从而根据application data数据和协商的对称加密算法解密。
2、DH算法
DH算法,如果是chrome或者firefox浏览器,可以设置导出pre-master-secret log,然后wireshark设置pre-master-secret log路径,这样就可以解密了。因为预主密钥是客户端本地通过算法生成,不经过网络传输,所以把浏览器中计算出的预主密钥导出给wireshark便可解密。
例如chrome启动时配置输出sslkeylog

google-chrome --ssl-key-log-file=~/sslkey/sslkeylog.log

然后wireshark导入sslkeylog,就可以解密ECDHE密钥协商算法的https流量:
wireshark导入sslkeylog
wireshark解密流量
3、中间人攻击
中间人攻击的思路是在客户端和服务器中间有个代理,客户端请求的流量被代理到中间人上,中间人再传递给服务器。而客户端需要安装中间人的CA证书,以便在浏览器中访问网站时,浏览器认可中间人伪造的CA证书。最典型的就是burpsuite解析https数据,实际就是利用了中间人攻击的原理。

参考文档:
https://xz.aliyun.com/t/2531
https://blog.csdn.net/mrpre/article/details/78025940
https://www.jianshu.com/p/7158568e4867
https://www.2cto.com/article/201610/555721.html
https://www.linuxprobe.com/linux-wireshark-https.html
https://www.cnblogs.com/huanxiyun/articles/6554085.html
Last modification:January 17th, 2021 at 08:14 pm