重新认识 HTTPS

466 阅读12分钟

首先,让我们先了解下什么是 HTTPS

看看下面的图片,你是否很熟悉?

从上面的图片中,可以看出两点:

  1. HTTPS 跟 HTTP 有关系(一样是访问网站,格式也差别不大,都是 aaa://bbb
  2. HTTPS 比 HTTP 更加安全(来自浏览器和安全软件的提示)

HTTP 是超文本传输协议,对应的 HTTPS 就是超文本传输安全协议。更多关于说明传输协议的内容就不过多涉及,在本文中只需要知道 HTTP 和 HTTPS 可以从网络上通过 URI 地址拿到 网页(HTML)、视频(mp4)、图片(png) 等资源文件。

比如上面两张图片,对应的网络地址(http://URI 或者 https://URI)如下:

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/11/25/16ea1c7f8f267a60~tplv-t2oaga2asx-image.image

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/11/25/16ea1cea567315d0~tplv-t2oaga2asx-image.image

很明显,上面的图片都是用的 https://URI 格式,URI 可以理解成某个资源文件对应的资源标识符。

那么,是否用了 HTTPS 协议资源就无法通过 HTTP 协议访问呢?

答案是不一定的,取决于网站是否强制使用某一种协议,一般是两种都可以的,有些是会自动重定向。上面两张图片地址同样可以用 http 协议访问,但是 www.google.com 就用了重定向。

按照图上面的箭头走势可以看出大致的请求流程:

  1. 请求 http://www.google.com/
  2. 状态码返回 307 Internal Redirect (表示重定向)
  3. 从响应头里面找到重定向地址 https://www.google.com
  4. 再次发起请求 https://www.google.com

我们进行下一个问题,既然 HTTP 和 HTTPS 都是用来请求资源文件的,为啥要用 HTTPS?

为啥要用 HTTPS,我们换个角度来回答——用 HTTPS 有什么好处?

从 HTTPS 的名字(超文本传输安全协议)就可以看出,它比 HTTP 更加安全。

那么 HTTPS 的传输安全有什么用呢?换句话说就是,假如传输不安全会发生什么?是否会给我造成损失?我们来假设一个下面的场景:

年少英俊的你(小豪)喜欢上了班上的班花小菲,但是你们不是同桌,你想跟她传纸条只能通过别人中转。中转的过程你无法保证没人打开纸条偷窥你俩的消息,同样也无法保证小菲收到的消息就是你写的原始消息,有可能被篡改。这是很阔怕的事情,如果被有心人利用,后果难以想象......

上面的场景中,小豪和小菲分别相当于客户端和服务器,传纸条就相当于数据传输,中转的人叫做中间人。假如你提交的是你的 QQ 号和 QQ 密码,那么被中间人获取到之后,可能会用你的 QQ 号找你的好友借钱等骚操作。

很早就有这种模拟 QQ 空间的登录页面,先是用让你感兴趣的标题引导到这个假冒的登录页面,你输入 QQ 号和密码之后,一般有两种:

  1. 记录你提交的信息,默认提示你输入错误,再次进入真正的 QQ 空间登录页面
  2. 接收你提交的信息,使用你的信息去登录真正的页面

无论哪一种都会泄露你的信息,然后就用的 QQ 号进行诈骗。

相信到了这里,应该明白网络安全的重要性。其实,网络安全并非只有上面的例子。

  • 前段时间,一个日本的宅男因为一张女偶像的照片,从瞳孔里的倒影结合谷歌地图找到其居住地址,从而实施猥亵。

  • 另外,照片信息里面很可能会有 GPS 信息,换句话说就是照片的拍摄地址可能会暴露。比如下面的图片:

倘若你还是觉得安全不重要,那就此打住吧。不然下面的内容大概不会让你感兴趣的。

认识到安全的重要性之后,我们来看看 HTTPS 是怎么实现安全性的。

HTTPS 是如何保证安全性的

继续上面的场景,我们先来想象一下,在你已经知道传输过程中可能会被截取消息之后,你要怎么避免呢?

拦截已经是无可避免的事情,那么有没有一种就算是拿到了消息也无法知道确切的消息内容的方法呢?加密可以做到这一点。

对称加密

你和小菲约定好了一个加解密的密匙,你发送出去的消息用这个额密匙加密,小菲收到消息之后用这个密匙解密。这样就算中间人拦截到了消息,也没法知道真正的内容。你们俩又可以愉快的聊天了。

问题似乎就这样完美的解决了,但是我们忽略了一个前提:双方是怎么约定的密匙?网络世界不同于现实世界,两个人面对面说悄悄话就可以商量好用啥密匙。网络里要实现双方约定,同样需要建立连接、传输数据。然而在传输过程中,还是逃不过中间人的魔爪。

非对称加密

为此你买了两个消息盒子,你和小菲一人一个,盒子上面有个开口,仅能放入纸条;还有一把锁,只能用钥匙打开。当你要给小菲发消息时,你就叫小菲把他自己的盒子给你,你把纸条放进盒子里,再送回去。这样小菲就能用她自己的钥匙打开盒子,取出你的消息。小菲给你发消息也是类似的过程。

上面的过程就是非对称加密,和对称加密不一样的是:

  • 对称加密用同一个密匙加解密,非对称加密使用一对密匙加解密
  • 对称加密密匙不能泄露,非对称加密的解密密匙不可以泄露

类比上面的流程,消息盒子就是公钥,开锁的钥匙就是私钥。盒子可以给任何人,只要钥匙还在你手上,就只有你能看到盒子里的内容(忽略盒子的质量问题和暴力破坏)。

然而很快你发现消息的传递速度变慢了,因为每次写纸条都得要装到盒子里面去,拿到盒子之后还得开锁,以前一节课可以发二十张纸条,现在只能十张了。你开始怀念当初那种对称加密的聊天速度了,但是又没好办法,只能暂时搁置了。

另一边,传递盒子的过程中,会经过中间人小明传递。小明也喜欢小菲,对你和小菲聊天很不爽,但是拿到盒子也没法打开,只能想别的办法。偶然间看到盒子的底部有写着made in xxx 工厂,一下子来了灵感:我也去买个外观一模一样盒子,钥匙在我手里,不管你们谁发消息,都要先经过我传递盒子,我只要把盒子换成我的,那么消息就可以被我知道了,然后我再把消息放到你们的盒子里面去。这样谁都不知道我其实已经篡改了消息了。

原本对应的流程如下:

小明的操作如下:

你再次接收到了消息,但是发现消息内容不是小菲的笔记,而是小明的笔记,你知道了你的消息还是被小明篡改了。经过多次尝试,重点关注小明的动作之后,你知道了原因。

正好你也不满足当前聊天的速度,提高安全性(防止篡改)和加解密速度势在必行了。

TLS/SSL

防止信息篡改比较容易,使用 Hash 散列计算签名就行,这样能保证只要信息输入被篡改那么计算出来的签名就不一致。

加解密速度没法提高,但是换一个思路:拖慢速度的原因是每次消息都需要用非对称加密。倘若我们一开始用非对称加密传输对称加密的密匙,接下来的消息通通用对称加密密匙来加解密,速度就不再是问题。

我们想象下现实世界是怎么保证安全性的,我们会放心地把钱存银行,是因为国有控股,具有公信力。那么对应的,网络世界也有类似的机构,CA 认证机构。

大致的原理是:

  1. 生成非对称密匙
  2. Hash (网站公钥 + 网站信息 + 其他信息)= 消息摘要
  3. 非对称加密( CA 认证机构的私钥 + 消息摘要)= 数字签名
  4. 数字签名 + 网站公钥 + 网站信息 + 其他信息 = 数字证书(CA 证书)

防止消息篡改就是验证消息摘要是否相同:

完整的 HTTPS 请求基本流程如下:

重点就是客户端拿到服务器的数字证书之后,用浏览器内置的根证书去验证证书是否有效,然后双方协商加密密匙,用非对称加密传输。

关于证书的验证,涉及到证书链,大概的原理就是根证书是自己信任自己,然后颁发中间证书,网站的数字证书多半是由中间证书颁发的;如果是验证就是反向进行,由谁颁发的就由谁验证,这样一级级自下而上直到根证书。

单向认证与双向认证

以上的过程就是 HTTPS 的单向认证,所谓单向认证就是指仅仅验证了服务器端证书的有效性,换句话说就是能保证服务器端是经过认证机构信任。

理解了这一点,那么双向认证也就不难理解了。在单向认证的基础之上,验证完服务器端的数字证书之后,客户端发送自己的证书给服务器,然后双方协商加密方式,最后由客户端生成密匙进行通信,就是双向认证了。

对比单向认证,双向认证多了一个双方协商加密方式步骤。主要是因为对称加密方式并不是只有一种解决方案,很可能其中某一方只支持特定的对称加密方式。一旦双方不经过协商,整个 SSL/TSL 的安全通道就无法建立。所以哇,沟通还是很重要的,否则可能就白费功夫了。

另外一点,客户端的证书一般都是自签证书(可以理解为上面的根证书,也就是自己信任自己),所以服务器这边一般是验证有效期和获取证书里面的公钥。可以想象下,客户端为啥不用 CA 机构颁发的证书:

  1. CA 机构颁发的证书要收费,还是按年收费,还不便宜(1000+ RMB/年)
  2. 一旦使用 CA 机构颁发的证书,服务器校验需要内置对应的根证书

双向认证流程如下:

网络攻防方面

这一块属于拓展模块。上面已经提到了浏览器内置了一些受信任的 CA 根证书(也叫做自签证书),并且根证书是自己验证自己。

那么我弄一个自签证书,放到自己的浏览器里,由我的自签证书颁发的网站也会受信任了吧。

虽然是这样没错,但是如果你想拦截别人的通信,需要在他的浏览器里安装你的自签证书。

抓包

抓包就是这样做的,基本原理就是:

  1. 在客户端安装自签证书
  2. 截获客户端的 HTTPS 请求,伪装成中间人客户端去向服务端发送 HTTPS 请求
  3. 接受服务端返回,用自己的证书伪装成中间人服务端向客户端发送数据内容

反抓包

如何防止被抓包呢?上面能成功抓包的原因是因为客户端相信了来自中间人的伪造证书,误以为是服务器的证书。

那么解决办法就是做一次验证呗,假如客户端存储了一份服务端的证书,两两相比较就知道是否被抓包了。这种方法也叫做 SSL-Pinning 技术,一般有两种方式:

  • 证书锁定: 需要在客户端代码内置仅接受指定域名的证书,而不接受操作系统或浏览器内置的 CA 根证书对应的任何证书,通过这种授权方式,保障了 APP 与服务端通信的唯一性和安全性,因此客户端与服务端(例如 API 网关)之间的通信是可以保证绝对安全。但是 CA 签发证书都存在有效期问题,缺点是在 证书续期后需要将证书重新内置到 APP 中。
  • 公钥锁定: 提取证书中的公钥并内置到客户端中,通过与服务器对比公钥值来验证连接的正确性。制作证书密钥时,公钥在证书的续期前后都可以保持不变(即密钥对不变),所以可以避免证书有效期问题,一般推荐这种做法。

总结

其实还有突破 SSL-Pinning 去抓包的策略:修改验证证书有效的函数,直接返回 true,这样就可以突破了。

简单总结下,本文从网址开始,解释 HTTP 和 HTTPS 的区别和联系;然后提到网络安全的重要性;之后是 HTTPS 涉及到的几种加密方式;再之后提到了 CA 认证机构和 SSL/TLS;最后拓展了抓包相关思路。

希望对大家了解 HTTPS 有所帮助。