TLS: Extended Master Secret 扩展
1. TLS 协议中存在的一个安全问题
在 TLS (version 1.2) 的基本协议设计中, master secret 的计算方式依赖于 pre master secret, client.random, server.random, 而与握手过程中其他参数无关(比如,服务器证书)。
TLS 中master secret 的计算方法:
master_secret = PRF(pre_master_secret, "master secret",                ClientHello.random + ServerHello.random)                [0..47];
因此,就存在一种可能的被攻击的漏洞。
如何实现攻击:
假定:
- 客户端是 C,攻击者是 A, 服务器是 S。
 - 这里 C 被 A 所欺骗,而错误的建立了 TCP 连接到 A,把 A 当作了 S。
 - 握手流程中使用 RSA Key 交换算法。
 
那么攻击过程大体如下:
- C 发送 
ClientHello, 被假服务器 A 所接收。 然后 A 把它转发给 S。 - S 收到 
ClientHello之后,回复ServerHello到 A。 然后 A 将它转发给 C。 - S 发送 
Certificate到 A, 然后 A 替换掉来自 S 的Certificate, 并将 A 自己的证书发送给 C。 - S 发送 
ServerHelloDone到 A, 然后 A 转发它到 C. - C 发送 
ClieentKeyExchange到 A。 这个数据包中包含pre_master_key, 并且客户端使用假服务器 A 的证书公钥对其进行加密。 当 A 收到这个包之后,可以使用自己的私钥对其进行解密。 然后 A 使用 S 的公钥对其进行加密,构建一个新的ClieentKeyExchange, 并发送给 S。 - C 发送 
Finished到 A, 然后 A 根据它和 S 握手的参数重新计算一个新的Finished并发送给 S。 - S 发送 
Finished到 A, 然后 A 根据它和 C 握手的参数重新计算一个新的Finished并发送给 C。 
这次,A 同时和 C 和 S 建立了两条 TLS 链接。 并且这两条链接所使用的 master_key是相同的。 这也就意味着攻击者 A 能够透明的在 C 和 S 之间转发 ApplicationData 数据包,并查看通信过程中的所有数据。
2. Extended Master Secret 如何解决这个安全问题?
为了解决上述的安全问题,TLS 中引入了一个新的扩展 Extended Master Secret. 它如何解决这个问题?
它通过改变 master key 的计算方式来解决这个问题。回顾上面的计算公式,我们看到,旧的计算方式中, master key 只与 pre master secret, client.random, server.random 相关, 以至于握手过程中其他数据包没有被计算进来。 而 Extended Master Secret 要求使用更多的握手数据包来计算master key, 从而规避这个问题。
启用Extended Master Secret, master key 的计算方式如下:
master_secret = PRF(pre_master_secret, "extended master secret",                session_hash)                [0..47];
- 使用新的 
label: “extended master secret”, 原先是 "master secret". - 使用新的 
seed: session_hash 
session_hash 如何计算:
session_hash = Hash(handshake_messages)
handshake_messages : 从握手开始的 ClientHello 到 ClientKeyExchange 之间所有接受和发送的握手包
(all handshake messages sent or received, starting at the ClientHello up to and including the ClientKeyExchange message, including the type and length fields of the handshake messages. )
Hash: 使用和计算 Finished 相同的算法。
3. 如何启用这个扩展
这个扩展由客户端和服务器通过协商来决定是否启用。
对于想要使用这个扩展的客户端来说,需要在 ClientHello 中包含这个扩展。如果服务器愿意使用这个扩展,那么它需要在 ServerHello 中也包含这个扩展。 如果服务器拒绝使用这个扩展,那么在 ServerHello 不包含这个扩展即可。
4. 示例:
我们这里通过一个实例来展示关于这个扩展的协商过程:
- 
CientHello
Transport Layer SecurityTLSv1.2 Record Layer: Handshake Protocol: Client HelloContent Type: Handshake (22)Version: TLS 1.2 (0x0303)Length: 166Handshake Protocol: Client HelloHandshake Type: Client Hello (1)Length: 162Version: TLS 1.2 (0x0303)....Extension: extended_master_secret (len=0)Type: extended_master_secret (23)Length: 0.... - 
ServerHello
Transport Layer SecurityTLSv1.2 Record Layer: Handshake Protocol: Server HelloContent Type: Handshake (22)Version: TLS 1.2 (0x0303)Length: 95Handshake Protocol: Server HelloHandshake Type: Server Hello (2)Length: 91Version: TLS 1.2 (0x0303)....Extension: extended_master_secret (len=0)Type: extended_master_secret (23)Length: 0.... 
这个扩展中不包含任何数据,仅仅就是一个标志而已。