HTTPS详解

独奏

学习思考|2016-1-13|最后更新: 2023-2-23|
type
Post
status
Published
date
Jan 13, 2016
slug
summary
tags
HTTP
category
学习思考
icon
password
移动端的安全问题越来越受到重视,苹果对 iOS 开发已经默认要求使用 HTTPS 了,HTTPS 的安全性毋庸置疑,在移动端使用 HTTPS 通信,可以省去很多安全方面的困扰。这里就简单说一下 HTTPS。

通信过程

notion image
HTTPS 通信过程
  1. 客户端发出握手请求(Client Hello),包含以下信息:
      • 支持的协议版本,比如TLS 1.0版。
      • 一个客户端生成的随机数(random_1),这个随机数既需要客户端保存又需要发送给服务器。
      • 支持的加密方法,比如RSA公钥加密。
      • 支持的压缩方法。
  1. 服务器回复(Server Hello),包含以下信息:
      • 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。
      • 一个服务器生成的随机数(random_2)。
      • 确认使用的加密方法,比如RSA公钥加密。
      • 服务器证书。
      • 如果服务器需要确认客户端的身份,就会再包含一项请求,要求客户端提供”客户端证书”。比如,金融机构往往只允许认证客户连入自己的网络,就会向正式客户提供USB密钥,里面就包含了一张客户端证书。
  1. 客户端回应,包含以下步骤:
      • 验证服务器证书的合法性,证书合法性包括:证书是否过期,发行服务器证书的 CA 是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配。如果合法性验证没有通过,通讯将断开;
      • 客户端使用一些加密算法(例如:RSA,Diffie-Hellman)产生一个48个字节的Key,这个Key叫PreMaster Secret。该PreMaster Secret用服务器公钥加密传送,防止被窃听
      • 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
      • 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供服务器校验。
      • 如果前一步,服务器要求客户端证书,客户端会在这一步发送证书及相关信息。
  1. 服务器回应,服务器通过上面的三个随机数(random_1,random_2,PreMaster Secret),计算出本次会话的『会话密钥(session secret)』,然后向客户端发送下面信息
      • 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
      • 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发送的所有内容的hash值,用来供客户端校验。
至此,服务器和客户端的握手阶段全部结束,接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用『会话密钥(session secret)』对内容做对称加密。

PreMaster Secret 说明

PreMaster secret是在客户端使用RSA或者Diffie-Hellman等加密算法生成的。它将用来跟服务端和客户端在Hello阶段产生的随机数结合在一起生成Master secret。在客户端使用服务单的公钥对PreMaster secret进行加密之后传送给服务端,服务端将使用私钥进行解密得到PreMaster secret。也就是说服务端和客户端都有一份相同的PreMaster secret和随机数。
premaster_secret 长度为 48 个字节,前 2 个字节是协议版本号,剩下的 46 个字节填充一个随机数。结构如下:
Struct { byte Version[2]; byte random[46]; }
PreMaster secret前两个字节是TLS的版本号,这是一个比较重要的用来核对握手数据的版本号,因为在Client Hello阶段,客户端会发送一份加密套件列表和当前支持的SSL/TLS的版本号给服务端,而且是使用明文传送的,如果握手的数据包被破解之后,攻击者很有可能串改数据包,选择一个安全性较低的加密套件和版本给服务端,从而对数据进行破解。所以,服务端需要对密文中解密出来对的PreMaster版本号跟之前Client Hello阶段的版本号进行对比,如果版本号变低,则说明被串改,则立即停止发送任何消息。

Master secret 说明

需要注意的是,上面握手过程中存在三个Key(random_1,random_2,PreMaster Secret),而且服务器和客户端都保留着这三个值,客户端和服务端通过这三个值计算出同样的Master secret。Master secret是由系列的hash值组成的,结构如下:
notion image
Master secret 结构
其中,Client/Server write MAC key 是用来对数据进行验证的,Client/Server write encryption Key 是用来对数据进行加解密的会话密钥(session secret)。
关于Master Secret的计算请参考《Htttps SSL/TLS Session Secret(Key)计算》
至于为什么一定要用三个随机数,来生成Master Secret,由于SSL协议中证书是静态的,因此需要引入一种随机因素来保证协商出来的密钥的随机性。SSL协议不信任每个主机都能生成完全随机的随机数,所以这里需要服务器和客户端共生成3个随机数,每增加一个自由度,随机性就会相应增加。
同时需要注意前两个随机数都是明文传输的,窃听者是可以轻易获取到的,只有最后一个 PreMaster Secret 是加密传输的,只有拥有服务器私钥才能解密,一旦 PreMaster Secret 泄露,那么本次通信就就完全可被破解了。

应用数据传输

在所有的握手阶段都完成之后,就可以开始传送应用数据了。应用数据在传输之前,首先要附加上MAC secret,然后再对这个数据包使用write encryption key进行加密。在服务端收到密文之后,使用Client write encryption key进行解密,客户端收到服务端的数据之后使用Server write encryption key进行解密,然后使用各自的write MAC key对数据的完整性包括是否被串改进行验证。

对称加密 & 非对称加密

HTTPS 的通信过程中只在握手阶段使用了非对称加密,后面的通信过程均使用的对称加密。尽管非对称加密相比对称加密更加安全,但也存在两个明显缺点:
  1. CPU 计算资源消耗非常大。一次完全 TLS 握手,密钥交换时的非对称解密计算量占整个握手过程的 90% 以上。而对称加密的计算量只相当于非对称加密的 0.1%,如果应用层数据也使用非对称加解密,性能开销太大,无法承受。
  1. 非对称加密算法对加密内容的长度有限制,不能超过公钥长度。比如现在常用的公钥长度是 2048 位,意味着待加密内容不能超过 256 个字节。
所以公钥加密目前只能用来作密钥交换或者内容签名,不适合用来做应用层传输内容的加解密。
非对称密钥交换算法是整个 HTTPS 得以安全的基石,充分理解非对称密钥交换算法是理解 HTTPS 协议和功能的关键。

证书

下面是使用 chrome 访问 Google 时查看的证书详细信息
notion image
Google HTTPS证书
数字证书的格式普遍采用的是X.509V3国际标准,一个标准的X.509数字证书包含以下一些内容: - 证书的版本信息; - 证书的序列号,每个证书都有一个唯一的证书序列号; - 证书所使用的签名算法; - 证书的发行机构名称,命名规则一般采用X.500格式; - 证书的有效期,通用的证书一般采用UTC时间格式,它的计时范围为1950-2049; - 证书所有人的名称,命名规则一般采用X.500格式; - 证书所有人的公钥; - 证书发行者对证书的签名。
证书以链的形式组织,上级标识该证书的签发机构,验证证书的时候也是顺着这个链向上层层验证的,只有所有证书都是受信的,整个验证结果才是可信的。那么根证书是如何验证的呢?根证书是自信任的,在操作系统或者浏览其中都会默认一些受信任的 CA 机构根证书。
除非对这个根证书有绝对的信任才可以加入信任列表中,因为根证书是有权签发子证书的,如果根证书失信,那么对应的子证书的可信性就无从谈起,那么与使用相应证书的 HTTPS 网站通信的安全性就得不到保障了。当访问12306的时候,网站会提示把其提供的根证书加入到可信任列表里面,这就是为什么许多人反对这种做法的原因了。另外中国互联网信息中心(CNNIC)也曾发布过用于中间人攻击证书,详情可以参考这篇文章:谷歌称CNNIC发布伪造CA证书
Mac 用户可以通过 钥匙串->系统根证书 查看系统默认信任的所有根证书,如果想取消信任(比如 CNNIC证书),可以双击,改为永不信任

安全性

针对 HTTPS 的攻击最主要的就是 SSL 劫持攻击,其分为两种:

HTTPS 替换为 HTTP

这种方式就是攻击者充当中间人和服务器通信,然后把相应的通信内容通过 HTTP 协议发送给客户端,由于 HTTP 协议是未加密的,于是就可以截获用户的访问数据。
这种攻击方式比较简单,通过代理,可以很容易的把 HTTPS 变成 HTTP,这个一方面需要用户留意网站是否有从 HTTPS 跳转到 HTTP 的行为,另一方面服务器也可以通过配置将所有HTTP的请求强制转移到HTTPS上。

HTTPS 劫持

这种方式攻击者为了获得 HTTPS 的明文传输内容,需要充当中间人,替换服务器发给用户的包含公钥的证书。攻击者既和用户之间建立了 HTTPS 链接,又和服务器建立了 HTTPS 链接。
在上面握手建立的过程中,由于用户的公钥是攻击者生成的,所以攻击者可以轻易获得握手中的数据。也就可以获取到和用户通信过程中的对称加密的密钥,攻击者可以通过密钥获取用户发送的数据,同时在使用和服务器通信的密钥加密后再发送给服务器。
这种攻击方式也有一个明显的问题就是攻击者生成的证书几乎是不可能被用户信任的,在这种情况下,用户浏览器通常会提示该网站的证书不可信,是否继续访问,这已经对用户进行了一个明显的警告了。
另外我们也可以通过这种对基于 HTTPS 的通信进行抓包分析。Mac 平台著名的抓包工具 Charles 就是基于这种方式,首先要求你信任一个它的证书,然后自己充当中间人对你与某个服务器的 HTTPS 通信进行抓包分析。

其它

除了上述两种攻击方式之外,就是由于程序漏洞造成的问题了,比如早期 HTTPS 曾被发现存在漏洞,但很快被修补了;再比如2014年 OpenSSL 爆出的『心脏出血』漏洞;再比如2015年爆出iOS 平台 AFNetworking 存在漏洞,导致上千个 APP 存在安全性风险。但是类似的问题相对来说还是比较少见的。
总体来说,HTTPS 本身是比较安全的,存在的问题用户也都是可觉察的,只要用户有相应的安全意识,涉及个人重要信息的网站使用 HTTPS 访问,同时注意网站证书是否可信,基本不会出现被劫持的情况。

参考