HTTPS

HTTPS 即 HTTP over SSL/TLS,是一种在加密信道进行 HTTP 内容传输的协议。

TLS (Transport Layer Security)的早期版本叫做 SSL(Secure Sockets Layer)。SSL 的 1.0、2.0、3.0 版本均已经被废弃,出于安全问题考虑广大浏览器也不再对老旧的 SSL 版本进行支持了,因此下文我们统一使用 TLS 名称。

TLS握手

1. 客户端发出请求(Client Hello)

由于客户端(如浏览器)对一些加解密算法的支持程度不一样,但是在TLS协议传输过程中必须使用同一套加解密算法才能保证数据能够正常的加解密。

客户端向服务器端提供的消息包括:

  • 支持的加密通信协议版本,如TLS 1.2

  • 一个客户端生成的随机数Random1

  • 客户端支持的加密套件(Support Ciphers)

2. 服务器回应(Server Hello)

Server Hello

服务器回应的消息包括:

  • 确认的使用加密通信协议版本,如TLS 1.2。如果客户端与服务器支持的版本不一致,服务器关闭加密通信

  • 一个服务器端生成的随机数Random2

  • 确认使用的加密算法

  • 数字证书认证机构(Certificate Authority,缩写CA)签发的服务器公开证书,证书中包含公钥

Certificate Request

对于非常重要的保密数据,服务端还需要对客户端进行验证,以保证数据传送给了安全的合法的客户端。服务端可以向客户端发出Certificate Request消息,要求客户端发送证书对客户端的合法性进行验证。

3. 服务器回应(Server Hello Done)

Server Hello Done通知客户端Server Hello过程结束。

4. 客户端回应(Certificate Verify)

如果服务端需要对客户端进行验证,在客户端收到服务端的Server Hello消息之后,首先需要向服务端发送客户端的证书,让服务端来验证客户端的合法性。

Certificate Verify

客户端根据自己的信任CA列表,验证服务器端的证书是否可信。如果证书不是可信机构颁布、或者证书中的域名与实际域名不一致、或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。如果证书没有问题,客户端就会从服务器证书中取出服务器的公钥。

Client Key Exchange

客户端生成一个随机数Random3(整个握手阶段出现的第三个随机数),然后通过服务器公钥加密得到长度为48字节的PreMaster Key,然后将PreMaster Key发送给服务器。

服务器端使用自己的私钥解密PreMaster Key得到客户端生成的随机数Random3。此时客户端和服务端都拥有Random1 + Random2 + Random3,两边再根据同样的算法就可以生成一份秘钥,握手结束后的应用层数据都是使用这个秘钥进行对称加密。

生成密钥过程中使用三个随机数的原因:

不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。

对于RSA密钥交换算法来说,PreMaster Key本身就是一个随机数,再加上hello消息中的随机数,三个随机数通过一个密钥导出器最终导出一个对称密钥。

PreMaster Key的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么PreMaster Key就有可能被猜出来,那么仅使用PreMaster Key作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上PreMaster Key三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。

Change Cipher Spec (Client)

客户端编码改变通知。即客户端通知服务端后面再发送的消息都会使用前面协商出来的秘钥加密了,是一条事件消息。

5. 客户端发出消息(Client Finish)

Encrypted Handshake Message (Client)

客户端将前面的握手消息生成摘要再用协商好的秘钥加密,这是客户端发出的第一条加密消息。服务端接收后会用秘钥解密,能解出来说明前面协商出来的秘钥是一致的。

6. 服务器回应(Server Finish)

Change Cipher Spec (Server)

服务端编码改变通知。即服务端通知客户端后面再发送的消息都会使用加密,也是一条事件消息。

Encrypted Handshake Message(Server)

服务端将握手过程的消息生成摘要再用秘钥加密,这是服务端发出的第一条加密消息。客户端接收后使用秘钥解密,能解出来说明协商的秘钥是一致的。

7. 完成TLS握手

此时双方已安全地协商出了同一份秘钥,所有的应用层数据都会用这个秘钥加密后再通过 TCP 进行可靠传输。

TLS证书机制

HTTPS 过程中很重要的一个步骤,是服务器需要有 CA 颁发的证书,客户端根据自己的信任 CA 列表验证服务器的身份。现代浏览器中,证书验证的过程依赖于证书信任链。

所谓证书信任链,即一个证书要依靠上一级证书来证明自己是可信的,最顶层的证书被称为根证书,拥有根证书的机构被称为根 CA。

根证书一般是操作系统自带的。不管是桌面系统Windows,MacOS还是移动端系统Android,IOS都会内置一系列根证书。随着操作系统本身的升级,根证书也会随着升级进行更新。

对浏览器而已,浏览器有选择信任某个根证书的权利。Chrome 浏览器一般是跟随系统根证书信任的。Firefox 浏览器通常是使用自带的一套证书信任机制,不受系统证书的影响。

中间人攻击

中间人攻击,指攻击者与通讯的两端分别建立独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。在中间人攻击中,攻击者可以拦截通讯双方的通话并插入新的内容。

SSL剥离

SSL剥离即阻止用户使用 HTTPS 访问网站。由于并不是所有网站都只支持 HTTPS,大部分网站会同时支持 HTTP 和 HTTPS 两种协议。用户在访问网站时,也可能会在地址栏中输入http://的地址,第一次的访问完全是明文的,这就给了攻击者可乘之机。通过攻击 DNS 响应,攻击者可以将自己变成中间人。

SSL剥离的防御——HSTS

HTTP强制安全传输技术(HTTP Strict Transport Security,缩写HSTS)是一套由互联网工程任务组发布的互联网安全策略机制,其作用是强制客户端(如浏览器)使用HTTPS与服务器建立连接。HSTS的基本机制是在服务器返回的响应中,加上一个特殊的头部,指示浏览器对于此网站,强制使用 HTTPS 进行访问:

Strict-Transport-Security: max-age=31536000; includeSubdomains; preload

可以看到如果这个过期时间非常长,就是导致在很长一段时间内,浏览器都会强制使用 HTTPS 访问该网站。

HSTS 有一个很明显的缺点,是需要等待第一个服务器的影响中的头部才能生效,但如果第一次访问该网站就被攻击呢?为了解决这个问题,浏览器中会带上一些网站的域名,被称为HSTS preload list。对于在这个list的网站来说,直接强制使用 HTTPS。

伪造证书攻击

假设在全程使用HTTPS的情况下,我们想访问www.google.com,但我们的DNS服务器被攻击了,指向的IP地址并非Google的服务器,而是攻击者的IP。当攻击者的服务器也有合法的证书的时候,我们的浏览器就会认为对方是Google服务器,从而信任对方。这样,攻击者便可以监听我们和谷歌之前的所有通信了。

可以看到攻击者有两步需要操作,第一步是需要攻击DNS服务器。第二步是攻击者自己的证书需要被用户信任,这一步对于用户来说是很难控制的,需要证书颁发机构能够控制自己不滥发证书。

伪造证书攻击的防御——HPKP

HPKP(Public Key Pinning Extension for HTTP)在HSTS上更进一步,HPKP直接在返回头中存储服务器的公钥指纹信息,一旦发现指纹和实际接受到的公钥有差异,浏览器就可以认为正在被攻击:

Public-Key-Pins: pin-sha256="base64=="; max-age=expireTime [; includeSubDomains][; report-uri="reportURI"]

和HSTS类似,HPKP也依赖于服务器的头部返回,不能解决第一次访问的问题,浏览器本身也会内置一些HPKP列表。

HPKP技术仍然不能阻止第一次访问的攻击问题,部署和配置HPKP相当繁琐,一旦网站配置错误,就会导致网站证书验证失败,且在过期时间内无法有效恢复。HPKP的机制也引来了一些安全性问题。Chrome 67中废除了对HPKP的支持,在Chrome 72中HPKP被彻底移除。

最后更新于

这有帮助吗?