HTTPS 总结

这是内部分享的资料,也是对前面几篇关于 HTTPS 相关文章的一个总结。现公开出来。前面的两篇关于 HTTPS 的文章链接如下:

下面是我使用 wireshark 进行抓包的文件:

package

可以下载下来使用 wireshark 打开后对比来看。

HTTPS TLS 层握手流程

  1. 客户端握手请求(Client Hello):
    • 支持的协议版本。
    • 客户端随机数(random_1),这个随机数既需要客户端保存又需要发送给服务器。
    • 支持的加密方法。
    • 支持的压缩方法。
  2. 服务器回复:

    server hello

    • 确认使用的加密通信协议版本。
    • 服务器随机数(random_2)。
    • 确认使用的加密方法。

      certificate

      发送服务器证书。

      server key exchange

      当服务端向客户端发送的证书中没有提供足够的信息的时候,还可以向客户端发送一个 Server Key Exchange。如使用 RSA 算法,则服务端可以在这里提供加密预主密钥(PreMaster Secret)的公钥。如使用 DH 算法,则这里传输 DH parameter。

      certificate request

      若服务端需验证客户端证书,需要发送客户端证书请求。

      server hello done

  3. 客户端回应:

    验证服务器证书的合法性。

    certificate

    如果前一步服务端需要客户端提供证书,则通过这里发送客户端证书

    client key exchange

    若使用 RSA 算法生成密钥对,则这里生成 PreMaster Secret 并用前面服务器发送过来的公钥加密。若使用 DH 算法,则这里传输 DH parameter

    certificate vertify

    只有在客户端发送了自己证书到服务器端,这个消息才需要发送。该消息是让服务端验证该客户端证书,证明客户端确实有该证书的私钥。

    change cipher spec

    编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。

    encrypted handshake message

    客户端向服务器端发送一个加密的报文(前面所有发送内容的摘要),如果服务器能够解密,并验证成功,说明两端密钥一致

  4. 服务器回应

    change cipher spec

    编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。

    encrypted handshake message

    服务器向客户端发送一个加密的报文(前面所有发送内容的摘要),如果客户端能够解密,并验证成功,说明两端密钥一致。

  5. application data

    传输使用公共密钥加密的数据

读懂加密方式

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

ECDHE_RSA: 协商密钥时使用的算法,ECDHE 用于密钥交换,RSA 用于身份认证。
AES_256_GCM: 数据交换时使用的加密算法
SHA384: 签名算法

链接重用

TLS 握手阶段需要9次请求,非常耗时。链接重用目前有两种方式

session ID

session ID的思想很简单,就是每一次对话都有一个编号(session ID)。如果对话中断,下次重连的时候,只要客户端给出这个编号,且服务器有这个编号的记录,双方就可以重新使用已有的”对话密钥”,而不必重新生成。

该方式类似服务端的 session,可以使用 session ID 作为该次回话的唯一 标识,缺点在于 session id 需要服务器做存储,对于服务器集群来说,需要专门维护 session ID,可能造成数据不同步的问题。

session ticket

这个session ticket是加密的,只有服务器才能解密,其中包括本次对话的主要信息,比如对话密钥和加密方法等。当服务器收到session ticket以后,可直接从中解密出对话密钥。

这种方式的优点就在于不需要服务器存储。缺点在于可携带的信息量有限。

CDN

网站为了加快访问速度通常会使用 CDN,如果使用外部 CDN,我们通常不会把私钥交给 CDN 服务商,针对这种场景 CloudFlare 公司提出了一种解决方案 —— Keyless SSL

上图中主要区别在于第四步,CDN 提供商拿到前一步由源服务器公钥加密过的密文后,通过安全的信道交给源服务器来解密,由源服务器提取会话秘钥或完成签名以后再提交给 CDN 节点。如此 CDN 就获得了此次回话的密钥。

Diffie-Hellman 算法

由于握手交换随机数的过程是不加密的,因此,如果有人窃听通信,他可以知道双方选择的加密方法,以及三个随机数中的两个。整个通话的安全,只取决于第三个随机数(Premaster secret)能不能被破解。

虽然理论上,只要服务器的公钥足够长(比如2048位),那么Premaster secret可以保证不被破解。但是为了足够安全,我们可以把协商密钥阶段通过 RSA 传输密钥,改为使用 Diffie-Hellman 算法(简称DH算法)生成密钥。

采用DH算法后,Premaster secret不需要传递,双方只要交换各自的参数,就可以算出一个相同的会话密钥。

该算法最大的问题在于不具备身份认证能力,很容易受到中间人攻击。因此在 HTTPS 中需配合使用 RSA 证书来做身份认证。

注:
DH 算法是一种密钥交换算法。
RSA 既可作为密钥交换算法,又可以作为签名认证算法。

安全性

前向安全性

前向安全性指的是,如果攻击者抓取并保存流量,那么将来私钥泄露后,攻击者也无法利用泄露的私钥解密这些流量。

斯诺登就曾曝光过 NSA 的『今日捕获,明日破解』政策。

RSA 协商密钥的安全性完全依赖于服务器端私钥的安全性,如果服务器端私钥泄露,则所有链接都不再安全。

而 DH 算法由于密钥协商过程中随机数并没有传输,因此即使私钥泄露,也无法获得会话的随机数,故而也就得不到会话密钥。因此是前向安全的。

TLS 层存在的安全隐患

降级

这种方式就是攻击者充当中间人和服务器通信,然后把相应的通信内容通过 HTTP 协议发送给客户端,由于 HTTP 协议是未加密的,于是就可以截获用户的访问数据。

这种攻击方式比较简单,通过代理,可以很容易的把 HTTPS 变成 HTTP,这个一方面需要用户留意网站是否有从 HTTPS 跳转到 HTTP 的行为,另一方面服务器也可以通过配置将所有HTTP的请求强制转移到HTTPS上。

另一种是加密协议降级,如劫持后在 client hello 时只提供有漏洞的加密协议。这种方式可以在服务器端禁用低安全性的协议来规避。

HTTPS 劫持

这种方式攻击者为了获得 HTTPS 的明文传输内容,需要充当中间人,替换服务器发给用户的包含公钥的证书。攻击者既和用户之间建立了 HTTPS 链接,又和服务器建立了 HTTPS 链接。

在上面握手建立的过程中,由于用户的公钥是攻击者生成的,所以攻击者可以轻易获得握手中的数据。也就可以获取到和用户通信过程中的对称加密的密钥,攻击者可以通过密钥获取用户发送的数据,同时在使用和服务器通信的密钥加密后再发送给服务器。

这种攻击方式也有一个明显的问题就是攻击者生成的证书几乎是不可能被用户信任的,在这种情况下,用户浏览器通常会提示该网站的证书不可信,是否继续访问,这已经对用户进行了一个明显的警告了。

当然,如果 CA 机构对证书的管理混乱也有可能造成这种劫持,如:

  1. 谷歌官方安全博客报道,谷歌发现CNNIC颁发了多个针对谷歌域名的用于中间人攻击的证书。
  2. 国内CA机构沃通错误颁发GitHub域名SSL证书
  3. 震网病毒曾盗取台湾某证书机构的数字证书,用来给自己的病毒签名。

另外我们也可以通过这种对基于 HTTPS 的通信进行抓包分析。Mac 平台著名的抓包工具 Charles 就是基于这种方式,首先要求你信任一个它的证书,然后自己充当中间人对你与某个服务器的 HTTPS 通信进行抓包分析。

其他

  1. OpenSSL 心脏出血漏洞
  2. 知名开源库AFNetworking曝SSL漏洞,2.5万iOS应用受影响
  3. Diffie-Hellman密钥交换协议存在安全缺陷
  4. NSA如何窃听Google的加密流量——当HTTPS遇到CDN

QA

1. 为何需要三个参数生成 Master Secret ?

由于SSL协议中证书是静态的,因此需要引入一种随机因素来保证协商出来的密钥的随机性。SSL协议不信任每个主机都能生成完全随机的随机数,所以这里需要服务器和客户端共生成3个随机数,每增加一个自由度,随机性就会相应增加。

同时需要注意前两个随机数都是明文传输的,窃听者是可以轻易获取到的,只有最后一个 PreMaster Secret 是加密传输的,只有拥有服务器私钥才能解密,一旦 PreMaster Secret 泄露,那么本次通信就就完全可被破解了。

2. 为何使用 RSA 协商密钥不直接使用证书公钥,而是通过server key exchange传输服务器密钥?

可能有几个原因

  1. 曾经美帝有出口限制,限制 RSA 在512比特以下,对称加密密钥限制40比特以下,如果超过512只能拿来签名,不能拿来加密。因此证书里头的RSA公钥长度超过512的不得不重新生成一对512长度的临时加密用的密钥,并将RSA公钥塞进消息体发出去。
  2. 服务器的证书只用做签名,不用做密钥交换,或者服务器没有证书。

3. Change Cipher Spec 有必要么?

Change Cipher Spec 用来通知对端,开始启用协商好的密钥做对称加密,内容只有1个字节。 这个协议是冗余的,在TLS 1.3里面直接被删除了。

扩展

Deffie-Hellman 密钥交换