探讨HPPTS

HTTPS,全称Hyper Text Transfer Protocol over Secure Socket Layer,是以安全为目标的HTTP通道。通俗来讲,HTTPS就是HTTP的安全版,即HTTP下加入SSL层。HTTPS的安全基础是SSL,因此加密的详细内容就依赖于SSL。后面我们会来详细了解HTTPS的通信过程和可能受到的攻击手段。

HTTPS

在说HTTPS之前先说说什么是HTTP。HTTP全称是Hypertext Transfer Protocol,即超文本传输协议,是应用层的协议。HTTP协议都是通过明文来传输的数据,不提供任何方式的数据加密,如果在通讯过程中被攻击者截取了报文,攻击者就可以直接阅读报文的信息,因此使用HTTP协议传输隐私信息是非常不安全的。

为了保证这些隐私数据能加密传输,网景公司在1994年设计了SSL(Secure Sockets Layer)协议,来加密HTTP协议传输的数据,提供了身份验证和加密通讯方法,这就是后来的HTTPS。在SSL 3.0的时候,IETF对SSL进行了升级,也即TLS(Transport Layer Security) 1.0。由于两者差别不是很大,所以我们粗略地也可以将TLS 1.0等价于SSL 3.0。现在,HTTPS都是使用TLS协议,但由于SSL出现的时间比较早,并且依旧被现在浏览器所支持,因此SSL依然是HTTPS的代名词。

HTTPS通信过程

HTTPS Process

1.客户端发出握手请求Client Hello,包含以下信息:

  • 支持的协议版本,比如TLS 1.0版。
  • 一个客户端生成的随机数(random_1),这个随机数既需要客户端保存又需要发送给服务器。
  • 支持的加密方法,比如RSA公钥加密。
  • 支持的压缩方法。

2.服务器回复Server Hello,包含以下信息:

  • 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。
  • 一个服务器生成的随机数(random_2)。
  • 确认使用的加密方法,比如RSA公钥加密。
  • 服务器证书。

如果服务器需要确认客户端的身份,就会再包含一项请求,要求客户端提供”客户端证书”。比如,开通网银的时候,一般会给客户一个硬件设备,比如U盾,里面就包含了一张客户端证书,客户登录的时候必须插入这个设备来提供证书才会允许访问。

3.服务器回复Server Hello done

4.客户端会验证服务器证书的合法性,证书合法性包括:证书是否过期,发行服务器证书的CA是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配。

数字证书的格式普遍采用的是X.509V3国际标准,一个标准的X.509数字证书包含以下一些内容:

Master Secret

  • 证书的版本信息;
  • 证书的序列号,每个证书都有一个唯一的证书序列号;
  • 证书所使用的签名算法;
  • 证书的发行机构名称,命名规则一般采用X.500格式;
  • 证书的有效期,通用的证书一般采用UTC时间格式,它的计时范围为1950-2049;
  • 证书所有人的名称,命名规则一般采用X.500格式;
  • 证书所有人的公钥;
  • 证书发行者对证书的签名。

证书以链的形式组织,上级标识该证书的签发机构,验证证书的时候也是顺着这个链向上层层验证的,只有所有证书都是受信的,整个验证结果才是可信的。根证书是自信任的,在操作系统或者浏览器中都会默认保存一些受信任的CA机构的根证书。

如果合法性验证没有通过,通讯将断开;

5.客户端使用一些加密算法(例如:RSA,Diffie-Hellman)产生一个48个字节的Key,这个Key叫PreMaster Secret。PreMaster Secret用服务器公钥加密传送,防止被窃听。

6.如果之前服务器要求验证客户端的证书,客户端会再发送证书及相关信息。

7.客户端发送Change cipher spec,表示随后的信息都将用双方商定的加密方法和密钥发送。

8.客户端发送Client finished报文,表示客户端的握手阶段已经结束。

9.服务器通过之前的三个随机数(random_1,random_2,PreMaster Secret),计算出本次会话的会话密钥(session secret)』

10.服务器回复Change cipher spec,表示随后的信息都将用双方商定的加密方法和密钥发送。

11.服务器发送Server finished,表示服务器的握手阶段已经结束。

至此,服务器和客户端的握手阶段全部结束,接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用『会话密钥(session secret)』对内容做对称加密

这个过程中,我们还需要进一步了解下两个名字:PreMaster Secret和Master secret:

PreMaster Secret

PreMaster secret是在客户端使用RSA或者Diffie-Hellman等加密算法生成的,将用来跟服务端和客户端在握手阶段产生的随机数结合在一起生成Master secret。为了防止窃听,客户端会使用服务器的公钥对PreMaster secret进行加密之后再发送给服务端。

premaster_secret 长度为 48 个字节,前 2 个字节是协议版本号,剩下的 46 个字节填充一个随机数。结构如下:

c
1
2
3
4
Struct {
byte Version[2];
byte random[46];
}

PreMaster secret前两个字节是TLS的版本号,这是一个比较重要的用来核对握手数据的版本号,因为在Client Hello阶段,客户端会发送一份加密套件列表和当前支持的SSL/TLS的版本号给服务端,而且是使用明文传送的,如果握手的数据包被破解之后,攻击者很有可能串改数据包,选择一个安全性较低的加密套件和版本给服务端,从而对数据进行破解,所以服务端需要对密文中解密出来对的PreMaster版本号跟之前Client Hello阶段的版本号进行对比,如果版本号变低,则说明被串改,则立即停止发送任何消息。

Master secret

服务器和客户端都保留握手过程中存在三个随机值(random_1,random_2,PreMaster Secret),双方都通过这三个值用同一个算法来计算出Master secret,确保双方的Master secret一致。Master secret是由系列的hash值组成的,结构如下:

Master Secret

其中,MAC key是用来对数据进行身份和完整性的验证,write encryption Key 是用来对数据进行加解密的会话密钥(session secret)。

关于Master Secret的计算可以参考TLS, Pre-Master Secrets and Master Secrets

至于为什么一定要用三个随机数来生成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,是不是就安全了呢?

可以说是,也可以说不是。

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

SSLStrip攻击

也就是将HTTPS替换为HTTP

SSLStrip攻击也需要将攻击者设置为中间人,之后将HTTPS访问替换为HTTP返回给浏览器,由于HTTP协议传输的数据是未加密的,从而截获用户访问的数据。举个例子,当我们访问hotmail.com的时候会重定向到一个https://login.live.com的一个HTTPS的地址上,SSLStrip会代替用户与服务器通信,并将这个地址改为http://login.live.com(注意这个地址在http后面没有s)返回给浏览器,此时如果用户继续登录的话,攻击者就会截取到用户的密码。

SSLStrip的工作原理:

  • 进行中间人攻击,劫持所有HTTP请求;
  • 将所有的HTTPS全部替换为HTTP;
  • 与受害者机器通过HTTP进行连接,同时与合法的服务器建立HTTPS连接;
  • 害者与合法服务器之间的全部请求都经过代理(攻击者服务器)进行转发。

这种攻击非常对普通用户非常具有迷惑性,但是防御却非常的简单:

-对于服务提供商(网站)

在配置HTTPS服务的时候加上“HTTP Strict Transport Security”配置项;
将所有HTTP的请求强制跳转到HTTPS上。

对于所有的关键信息,比如用户的账号和密码,加密之后再传输

-对于用户

对于用户来说,在访问那些支持HTTPS的网站的时候,在浏览器的地址栏输入URL时强制的加上“https://”,大多数用户平时不注意这点,比如访问gmail,我们一般就输入“gmail.com”,如果是输入“https://gmail.com”就可以避免SSLStrip的攻击。对于使用脚本实现地址跳转也需要注意这个问题,location.href之后的URL,一定要强制加上“https://”。

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 访问,同时注意网站证书是否可信,基本不会出现被劫持的情况。