(公众号无法点击外链,参考资料以及各种外部链接请“阅读原文”获取)
除了协议本身的漏洞之外,一些编程语言也可能编写出不安全的网络应用程序。
既然HTTP是不加密通信的,那么自然会好奇它是如何被窃听的。
所谓的窃听是因为TCP/IP模型的物理层、数据链路层、网络层这几层所需要的设备支持都不可能是个人用户所具备的东西,所以在这几个环节进行通信窃听是完全有可能的。
整个窃听的过程如下图,在网络信息通过网卡发出去的那一刻,网络包中间被“加工”的可能性就会急剧增加。这样的情况就好比一个快递从站点发出去的一刻,就有可能出现各种各样的情况。
此外加密通信并不是保证信息不被窃听,而是在窃听方拿到网络包之后无法破解明文信息内容,这样“加密”的特性就算是达到了。
常见的窃听方式比如WireShark,可以对于请求进行抓包处理。
如何防止窃听
防止明文窃听通过加密进行保护处理的方式有两种:
无身份验证体现在下面几个方面:
进行身份验证
SSL/TLS 需要通过第三方符合资质的机构进行数字认证,能获得这一机构认证本身就是十分麻烦的事情,所以通常颁发认证证书的服务器基本都可以获得加密保障,同时确认请求方的证书能有效的控制请求来源,对于客户端也能清楚请求的对方是合法安全的。
请求在传输和响应的过程中遭到拦截并且篡改攻击的手段叫做中间人攻击(Man-in-the-Middle attack,MITM),在许多情况下这是很简单的(例如,在一个未加密的Wi-Fi[1] 无线接入点[2]的接受范围内的中间人攻击者,可以将自己作为一个中间人插入这个网络)。
一个中间人攻击能成功的前提条件是攻击者能将自己伪装成每一个参与会话的终端,并且不被其他终端识破。中间人攻击是一个(缺乏)相互认证的攻击。
如何防止篡改
针对中间人攻击,HTTP通常使用 MD5
和 SHA-1
等散列值校验的方法,以及用来确认文件的数字签名方法提高安全性。此外Web 网站也会提供相应的以 PGP(Pretty Good Privacy,完美隐私) 创建的数字签名及 MD5 算法生成的散列值。
但是这些手段依然无法完全保证PGP不会被篡改,HTTP本身的可靠保证过于缺乏 。
SSL协议可以验证参与通讯的一方或双方使用的证书,校验是否是由权威的受信任的数字证书认证机构颁发,并且能执行双向身份认证。
PGP 是用来证明创建文件的数字签名,MD5 是由单向函数生成的散列值。
以上内容便是HTTP本身暴露的许多缺陷导致的信息泄漏问题,也是为什么要引入SSL/TLS 协议来强化HTTP的协议的几个理由。下面我们来聊聊SSL/TLS的历史。
现在我们讨论的SSL实际上是TLS,因为SSL协议本身的各种问题早已经被废弃了,目前主流的SSL实际上使用的是TLS的协议规范。
但是因为SSL被广为流传,结合历史原因,所以依然沿用这样的说法并不会产生歧义。
接着我们得明白HTTP+ 加密 + 认证 + 完整性保护=HTTPS
这个HTTPS的含义。
SSL/TLS 也是类似Cookie和Session一样,在不干扰协议本身运作的情况下对于HTTP协议本身进行保护和增强。
使用HTTPS请求之后,在浏览器输入地址的时候需要将原本的HTTP转化为HTTPS。
无论是OSI 七层模型还是TCP/IP模型,都为每个通信层的职责划分了明确的界限,HTTP是依赖TCP进行数据传输的,但是TCP为了保证单一职责和高效不会搭理HTTP的安全请求(本身也没有),他只负责数据包的收发,所以TCP是不能随便动的。而HTTP同样历史发展悠久,也难以在短时间内对于协议修订和增强。
可以看到,HTTP 是应用层协议,TCP是传输层协议,HTTP依赖TCP完成数据传输,所以 SSL/TLS 肯定是在应用层或者占据着传输层?
传输层必不可能,因为无法HTTP兼容,放到应用层这一说法其实也不完全准确。实际上SSL在TCP和HTTP的中间,类似处在两个应用的夹层里面,也就是所谓的架构难题的绝招 -- 遇事不决加一层。(因为干涉任意一层都引出更多的问题)。
中间夹层不知道为什么让我想到了《黑客帝国3》的那个车站。
SSL协议
明白了SSL/TLS 所处位置,我们继续了解SSL/TLS 的历史。
在许多参考资料中很多时候我们一会儿看到SSL的描述,一会儿看到TLS的描述,首先得再分清两者本身的定义。
如书中所言:
看似是协议和“伪通信层”的东西两个不同的东西,实际上SSL是TLS的前身,或者说TLS出现的本意就是为了替换SSL而出现的“竞品”。
SSL最早出现,出道即拉胯。随着历史发展发现SSL总是存在这样那样的缺点被人诟病。TLS乘胜追击逐渐取代SSL,到了目前最新的版本是TLS1.3(已经有了一半左右的普及度)。
这里参考维基百科的介绍,大致介绍TLS/SSL 的历史。
感兴趣想要阅读原文的童鞋可以看看“参考资料”。
弃用原因:- 消息认证使用 MD5 。有安全意识的用户已经不再使用 MD5 [RFC6151]。- 握手消息不受保护。
Consension Development
参考实现。所以SSL1.0到3.0都是比较坑的玩意儿,难怪会全面转向TLS,在2018年,谷歌、微软、苹果同时声明废弃TLS1.1、TLS1.0的使用,目前有99% 的服务器支持 TLS 1.2,基本已经完成TLS全面普及。
TLS 并不是在SSL出现问题之后才出现的,而是在SSL3.0出现之后开始修订。
MD5–SHA-1
被 SHA-256
取代,并带有使用密码套件指定 PRF 的选项。MD5–SHA-1
函数被 SHA-256
替换,并带有使用特定于密码套件的哈希算法的选项。但是完成的消息中的哈希大小仍限制必须至少为 96 位。MD5–SHA-1
被替换为握手期间协商的单个哈希,默认为 SHA-1
。MD5
和 SHA-224
加密哈希函数的支持。许多材料会把TLS/SSL 的SSL放在后面,目的是考虑TLS是目前的主流,放在前面是较为合适的。
所以用现在的眼光看其实SSL早就已经被禁止了,目前主流的HTTP加密传输是基于TLS实现的。此外维基百科上有几张图介绍TLS对比SSL的优势,可以较为直观展示两者的优缺点。
算法
兼容性
密码
密码
数据完整性
网站支持
此外,根据2022年的数据显示,TLS1.3 的覆盖率和 HTTP2.0差不多,但是TLS1.2 经过这几年普及基本全方位支持。
在了解SSL细节之前,我们需要先讲解加密方法:公开密钥加密 和 共享密钥加密。
共享密钥加密加密是通信双方持有同一把钥匙加解密信息,所以这种加密方式也叫做对称密钥加密或者共享密钥加密。
共享密钥加密
共享密钥最大的问题是钥匙传输给对方的过程中有可能遭到劫持,一旦传输密钥遭到劫持,共享密钥加密的方式就相当于作废了。
中间人攻击只需要拿到密钥,双方传输加密报文的时候拦截请求数据并且伪造自己的数据,就可以同时“剽窃”双方向的敏感信息。
为了处理这个问题,需要使用公开密钥加密对于共享密钥加密对加密方式进行了改进。
改进方式很简单那就是把钥匙换成一把只能用于加密,这把钥匙可以公开对外使用,而另一把只能用于解密,只有服务端的私钥可以解开公开密钥加密的信息,外部无法通过公钥破解。
如果能在短时间内快速的进行因式分解,那么全世界所有的密码都是透明的。有时候解密不一定是无法破解,而是破解的代价在现实上“不可能”,比如需要花费上千年的时间破解一串密码,等到破解那时候。。。。可能被破解的资源都没了。
公开密钥加密的最大特点是加密和解密的钥匙并不是同一把,两边对于密文的加解密方式不一样,所以这样的加密方式也别叫做 非对称密钥加密。
公开密钥加密
HTTPS并不是完全使用公开密钥加密或者共享密钥加密,而是通过两种加密混合的方式进一步提升安全。
共享密钥的问题在于密钥泄露的安全性问题,而公开密钥加密因为加解密的钥匙不是同一把,需要花费更多的操作运算和验证。
HTTPS在设计的过程中基于安全和速度的考虑,最终的决定是在连接握手的过程中使用非对称密钥加密确保安全,在服务器非对称加密验证通过之后,会返回稍后需要共享对称加密的密钥信息。在握手完成之后,在确保安全的前提之下, 使用对称加密的密钥进行共享对称加密的信息交互。
需要注意这里提到的加密认证是单向认证,也就是说只会验证服务端的真实可靠性,服务端无法准确保证客户端是可靠的(但是可以确保传输是安全的)。 客户端认证只在特殊的服务上会用到,大部分服务更多使用服务端单向认证,因为多数服务就是设计给所有人都可以访问的。
HTTPS混合加密
混合加密的方式看起来很靠谱和安全,但实际上依然存在问题,那就是无法证明公开密钥本身的真实性,为了理解这一点我们可以回顾共享密钥加密的描述图,在其中展示了攻击者在密钥传输的过程中盗取共享密钥的行为。
如果把这一行为替换为盗取公开密钥,则可以在客户端请求的时候劫持替换为攻击者自己的非对称加密密钥,之后的共享加密同样也是,可以被轻易获取。
具体的攻击过程如下:
在这样的攻击手段之下,为了保证客户端请求的服务器的真实性,采用第三方权威机构认证是合理的。
CA证书
为了解决这个问题,所采用的方式是通过第三方机构数字认证机构(CA,Certificate Authority),加入CA之后整个验证过程如下:
注意认证机关的公开密钥必须安全传给客户端,否则哪怕是数字认证本身还是有可能被篡改。为了规避这一个问题,许多浏览器会在安装的时候认证机构的公开密钥。
但是浏览器自带证书也有安全隐患,那就是数字认证机构遭到入侵后果不堪设想,历史上也真的发生过类似事件。
EVSSL证书
证书的作用是保证服务端的公开密钥的真实性,也可以验证服务器是否真实存在。
EV SSL 证书是基于国际标准的认证指导方针颁发的证书。主要的作用是提高网站的认可度。
有时候浏览器如果带HTTPS会出现绿色打勾的字样,这样做是提醒用户网站合法性。
客户端证书
客户端证书通常会出现在安全性要求极高的特殊业务当中,同时客户端本身需要支持SSL证书的开销,但是SSL的客户端证书只能证明请求的机器是没有问题的,但是无法保证
机构信誉
作为数字认证的机构一旦出现问题后果不堪设想,在过去曾经出现过数字认机构被黑客破解的情况,其对于SSL的公信力是一次巨大打击,
OpenSSL
OpenSSL 是可以让用户自己构建一套认证机构的开源程序,但是仅能作为本地使用。
如果出现外部访问,浏览器会提示“无效证书”等内容。
下面依照SSL的的交互步骤介绍HTTPS的通信过程。
这部分内容在[[《图解HTTP》- 用户身份认证]]里面的SSL流程一致,但是对于细节做了进一步扩展。
第一次握手:确认支持SSL
HandShake
就是握手的意思,报文中指定SSL版本和加密组件(加密算法和密钥长度等)。服务器支持SSL通信,返回Server Hello
应答,报文加入SSL的版本以及加密信息。服务器的加密组件需要根据客户端支持的加密通信方式筛选。第二次握手:服务端证书验证
Server Hello
应答。Certificate
报文,报文包含公开密钥证书,证书必须是 x.509 标准格式,包含服务端公钥、服务端域名、签发方信息、有效期等信息。Server Hello Done
表示SSL最初的握手协商已经结束。第三次握手:客户端确认 4. 客户端按照Client Key Exchange
回应,这个报文会在通信加密中使用Pre-mastersecret
的随机串,这个随机串第一步部分的第三个步骤已经偷偷完成加密了。5. 客户端继续发送 Change Cipher Spec
报文,告知服务器后续使用Pre-master secret
密钥加密通信(共享对称加密)。6. 客户端发送 Finished
报文。在这个报文中包含整个报文回应的校验和,客户端确认是否完成要根据服务器能否认识这一段加密报文为主。
第四次握手:服务端确认 7. 服务器同样发送 Change Cipher Spec
报文,表示自己认识客户端的加密信息。8. 服务器同样发送 Finished
报文,SSL连接建立完成。
至此SSL连接建立完成,通信将会受到协商好的共享密钥加密保护,应用层开始进行通信。应用层通信,服务端进行响应。
最后:断开连接 11. 客户端主动断开链接。断开连接会发送 close_notify
的报文。之后发送 TCP FIN
报文关闭通信。
注意在整个SSL四次握手的过程中,应用层发送数据时会附加一种叫做 MAC(Message Authentication Code)
的报文摘要。MAC 能够查知报文是否遭到篡改,从而保护报文的完整性。
最后是书中给的一幅图,了解整个加密过程(个人感觉画的一般,有点乱)
HTTPS通信
CBC 模式(Cipher Block Chaining)又名密码分组链接模式。此模式会把一个明文模块加密处理之后的下一个明文进行XOR运算。重叠之后对于运算结果进行加密处理。对于第一个明文进行加密之后,
最后是IETF 关于TLS协议原文的握手步骤,看起来比较抽象,但是实际上算是最权威的交互信息了,图片展示是TLS1.2的协议原文内容:
除开最后一次的数据交互之外,服务端和客户端需要四次握手才能完成。
也就是说从TCP连接到SSL连接完成,一共需要9次握手才能最终建立一个安全连接,所以其效率可想而知。
可以从参考资料获取相关内容和信息
下面的内容适合扩展阅读,由于本书涉及的内容比较入门,考虑读者阅读感受没有更加深入,后续有时间出一篇更加详细和完整的内容。
HTTPS - Wikipedia
Transport Layer Security - Wikipedia
看完这篇文章,我奶奶都懂了https的原理
彻底搞懂HTTPS的加密原理 - 知乎 (zhihu.com)
假如让你来设计SSL/TLS协议,你要怎么设计呢?-华为开发者论坛 (huawei.com)(优质文章)
The First Few Milliseconds of an HTTPS Connection (moserware.com)(优质文章)
TLS - SSL (Schannel SSP) Overview | Microsoft Docs
为什么 HTTPS 需要 7 次握手以及 9 倍时延 - 面向信仰编程 (draveness.me)