【Security】安全的 HTTP 的演化

Posted by 西维蜀黍 on 2019-05-13, Last Modified on 2024-01-16

HTTP是什么样的?

HTTP是属于应用层的协议,它是基于TCP/IP的,所以它只是规定一些要传输的内容,以及头部信息,然后通过TCP协议进行传输,依靠IP协议进行寻址,通过一幅最简单的图来描述:

Client发出请求,Server进行响应,就是这么简单。在整个过程中,没有任何加密的东西,所以它是不安全的,中间人可以进行拦截,获取传输和响应的数据,造成数据泄露。

基于对称加密(Symmetric Encryption)的HTTP

因为上图中数据是明文传输的,我们能想到最简单的提高安全性的方法就是在传输前对数据进行加密,如下图:

这种加密方式叫做:对称加密算法(Symmetric Encryption Algorhithm),即加密和解密使用同一个秘钥的加密方式。

好了,我们对数据进行加密了,问题解决了吗?

多个Client怎么办?

在上面的场景中,只有一个Client。但是在真实的情况中,一个Server,可能会被成千上万的Client,那情况会怎样呢?

为所有的Client都应用同一个秘钥A,这种方式很显然是不合理的。因为,破解了一个用户,所有的用户信息都会被盗取。

如果攻击者聪明一点,可以先作为一个正常的Client先与Server进行正常的通信,在获得了秘钥之后,再去窃听其他Client与Server的通信。


因此,我们要想一想,是不是还有别的办法呢?

相信大家都可以想到,如果对每一个Client都用不同的秘钥进行传输(如下图),是不是就解决这个问题了?

对称加密秘钥的传输问题

我们对每个Client应用不同的对称加密秘钥,那么对于这个秘钥,如何让Client或者Server知道呢,只能是在一端生成一个秘钥,然后通过HTTP传输给另一端:

那么这个传输秘钥的过程,又如何保证加密?如果被中间人拦截,秘钥也会被获取。也许你会说,对秘钥再进行加密,那又如何保证对秘钥加密的过程,是加密的呢?

好像我们走入了 while(1),出不来了。

基于非对称加密(Asymmetric Encryption)的HTTP

在对称加密的路上走不通了,我们换个思路,还有一种加密算法叫非对称加密算法(Asymmetric Encryption Algorithm),比如RSA。 非对称加密算法需要一对秘钥:公钥(public key)私钥(private key)

通过公钥加密的内容,只有通过私钥才可以解开;而通过私钥加密的内容,所有的公钥都可以解开(当然是指和私钥是一对的公钥)。

私钥只保存在服务器端,而公钥需要分别发送给不同的Client。因此,在传输公钥的过程中,可能出现被中间人获取的情况,这就是中间人攻击(Man-in-the-Middle Attack,MITM)。

中间人攻击(Man-in-the-Middle Attack,MITM)

具体地来说,当Client向Server请求公钥时,攻击者假装自己就是Server,并在截取到Client发来的"请求公钥"请求后,向真正的Server请求公钥;在获得真正的Server提供的公钥后,攻击者用自己的假公钥替换掉Server提供的真公钥,并返回给Client。

此后,当Client向Server发送数据时,攻击者收到Client发来的数据,先通过自己的私钥对数据进行解密,然后再用Server提供的公钥对数据进行加密,并传给Server。

Server自然地会用自己的私钥解密数据,并做相应的逻辑处理。当处理完成后,Server将数据使用自己的私钥进行加密,并返回给攻击者。

攻击者再用Server提供的公钥对数据进行解密,再对数据用自己的私钥进行加密,最终返回给Client。

中间攻击者在逻辑上位于Client和Server之间(在物理上,这个攻击者可以位于Client的局域网内,也可以位于Client与Server通讯时经过的一个网络节点)。

最终,中间攻击者即可以默默地获得Client和Server之间的通信内容,甚至修改通信内容(如下图所示),而不为两方所感知。

这个问题会发生的根本原因在于,Client拿到了一个假公钥(这个假公钥是由攻击者提供的,而不是Server提供的那个公钥),而且Client无法验证自己拿到的公钥是由谁生成的。

值得一提的是,在这种情况中,是可以保证Client与中间攻击者之间,和中间攻击者和Server之间的网络传输的安全性的(即,对于没有获得公钥或者私钥的另外攻击者而言,这两个过程的通讯内容均为乱码)。

引入权威第三方认证(Certificate Authority,CA)颁发的数字证书(Digital Certificate)

权威第三方认证(Certificate Authority,CA)

公钥被掉包,是因为Client无法分辨,传回的公钥是中间人,还是真正的 Server 生成的,这也是密码学中的身份验证问题。

我们知道,现实中有公证处,它提供的公证材料大家都信任,那在网络世界也可以建立一个这样的具备公信力的认证中心, 这个中心给大家颁发一个证书, 用于证明服务商的身份。

这个证书里除了包含这个服务商的基本信息之外,还有包括最关键的一环:服务商对应Server生成的公钥。

在网络世界中,这个权威且具备公信力的认证中心就叫Certificate Authority(CA)。而CA颁布的公证材料就是数字证书(Digital Certificate)

在介绍数字证书(Digital Certificate)之前,我们需要先知道什么是消息摘要(message digest)和数字签名(Digital Signature)。

消息摘要(message digest)

服务商将自己的基本信息和对应Server的公钥,用一个Hash算法生成一个消息摘要(message digest)

这个Hash算法有个非常重要的特性,只要输入数据有一点点变化,那生成的消息摘要就会有巨变,这样就可以防止别人修改原始内容。

但是,只依赖消息摘要(message digest),我们仍然无法防止中间人攻击(或者说Client无法判断公钥来自中间人,还是真正的Server)。

因为,Server将服务商的基本信息、服务商对应Server的公钥和对应的消息摘要(message digest)一起发给Client时,中间人仍然可以对这些数据进行拦截,并且将"服务商对应Server的公钥"替换为自己生成的公钥,再基于自己生成的公钥和服务商的基本信息重新生成一个新的消息摘要(message digest)。

数字签名(Digital Signature)

在消息摘要(message digest)的基础之上,Certificate Authority(CA)用它的私钥对消息摘要加密,形成数字签名(Digital Signature)

数字证书(Digital Certificate)

最终,把原始信息(包括服务商自己的基本信息和对应Server的公钥)和数字签名合并, 形成一个全新的东西,叫做数字证书(Digital Certificate)

这样,当Client要向Server请求数据时,Server先把它的证书发给Client, Client用同样的Hash 算法,将原始信息(包括服务商自己的基本信息和对应Server的公钥) 生成消息摘要,然后用CA提供的公钥对数字签名解密或者原始消息摘要。通过比较这两个消息摘要,就知道Server公钥有没有被篡改了。

数字证书的中间人攻击

你可能会想,即使我们引入了Certificate Authority,而且还使用Certificate Authority的私钥对消息摘要进行加密,以生成数字签名,会不会还会遭受中间人攻击。答案是不会。

因为,在攻击者不知道CA私钥的前提下,如果攻击者直接修改数字签名的值,当Client浏览器在执行数字证书校验时,用CA提供的公钥直接对修改后的数字签名进行解密,将会得到一个未知值。而这个未知值一定不会和将服务商基本信息和对应Server的公钥进行Hash算法后得到的消息摘要相等。

因此,在上图中两消息摘要相同,则一定能保证Client拿到的公钥一定是由Server对应的服务商提供的。

总结

安全传输保障前提

基于数字证书+非对称加密的HTTP安全传输机制依赖于以下前提:

  1. CA私钥的保密性;
  2. Client浏览器在执行数字证书校验的过程中,没有漏洞;
  3. Client浏览器的根证书验证机制没有漏洞(即,对数字签名进行解密时,使用的公钥如CA所期望,而未被攻击者在Client操作系统层面进行替换)。

数字证书的内容

X.509 应该是比较流行的 SSL 数字证书标准,包含(但不限于)以下的字段:

字段 值说明
对象名称(Subject Name) 用于识别该数字证书的信息
共有名称(Common Name) 对于客户证书,通常是相应的域名
证书颁发者(Issuer Name) 发布并签署该证书的实体的信息
签名算法(Signature Algorithm) 签名所使用的算法
序列号(Serial Number) 数字证书机构(Certificate Authority, CA)给证书的唯一整数,一个数字证书一个序列号
生效期(Not Valid Before)
失效期(Not Valid After)
公钥(Public Key) 可公开的密钥
签名(Signature) 通过签名算法计算证书内容后得到的数据,用于验证证书是否被篡改

除了上述所列的字段,还有很多拓展字段,在此不一一详述。

数字证书实例

我们来看看Google的证书:

Reference