前面几天学习 DNS 缓存的时候,了解到了 DNS 劫持和 HTTP 劫持,关于 DNS 劫持和 HTTP 劫持的区别,知乎上一位同学给出了有趣的比喻DNS劫持和HTTP劫持有什么区别?:
DNS 劫持:你输入的网址是 http://www.google.com
,出来的是百度的页面。
HTTP 劫持:你打开的是知乎的页面,右下角弹出唐老师的不孕不育广告(2018年更:右下角弹出:偶系渣渣辉)。
应对 HTTP 劫持最有效的方法就是 HTTPS。本文学习 HTTPS 相关的知识。在学习之前首先抛出三个问题:
- HTTPS 加密原理是什么?
- HTTPS 是否安全?为什么?
- 为什么抓包工具比如 Fiddler/Charles 能抓取 HTTPS 协议的包?
HTTPS 简介
超文本传输安全协议(英文:Hypertext Transfer Protocol Secure 缩写为:HTTPS,常称为 HTTP over TLS/SSL 或 HTTP Secure)是一种通过计算机网络进行安全通信的传输协议。HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包。关于 TLS/SSL 的详细内容,可以查看传输层安全性协议。
HTTPS 加密原理
传统的 HTTP 协议基于 TCP/IP 协议来传递数据,客户端通过三次握手与服务端建立连接,HTTPS 在传输数据之前需要客户端与服务端之间进行一次握手,在握手的过程中确立双方加密传输数据的密码信息。TLS/SSL 使用非对称加密、对称加密以及 HASH 算法。握手过程可以简单描述如下:
(1) 浏览器向服务器发送自己所支持的加密规则。 (2) 服务器从中选取一组加密算法与 HASH 算法,将自己的身份信息以证书(CA)的形式返回给浏览器。证书里面包含网站地址,加密公钥 S_PuKey 以及证书的颁发机构等信息。 (3) 客户端确认其颁发的证书的有效性,如果证书有效浏览器会生成一串随机数的密码 C_Key,并用证书中提供的公钥 S_PuKey 加密。然后客户端使用约定好的 HASH 计算握手消息,并使用生成的随机数 C_Key 对消息进行加密,最后将之前生成的所有信息发送给服务器。 (4) 服务器使用自己的私钥将信息解密取出密码 C_Key,使用 C_Key 解密浏览器发来的握手消息,并验证 HASH 是否与浏览器发来的一致。然后服务器使用密码加密一段握手消息,发送给浏览器。 (5) 浏览器解密并计算握手消息的 HASH,如果与服务端发来的 HASH 一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码 C_Key 并利用对称加密算法进行加密。
HTTPS 一般使用的加密与 HASH 算法如下:
- 非对称加密算法:RSA,DSA/DSS,用于在握手过程中加密生成的密码
- 对称加密算法:AES,RC4,3DES,用于数据传输过程中进行加密
- HASH 算法:MD5,SHA1,SHA256,用于验证数据的完整性
由于浏览器生成的密码是整个数据加密的关键,因此在传输的时候使用了非对称加密算法对其加密。非对称加密算法会生成公钥和私钥,公钥只能用于加密数据,因此可以随意传输,而网站的私钥用于对数据进行解密,所以网站都会非常小心的保管自己的私钥,防止泄漏。
TLS握手过程中如果有任何错误,都会使加密连接断开,从而阻止了隐私信息的传输。
SSL 证书验证失败有以下三点原因:
- SSL 证书不是由受信任的 CA 机构颁发的
- 证书过期
- 访问的网站域名与证书绑定的域名不一致
HTTPS 安全吗?
HTTPS 是否安全,是一个相对的概念,从服务器身份认证,保护交换数据的隐私性和完整性方面来说,它是安全的,但是它也有自己的局限。
TLS/SSL 协议依赖浏览器和服务器所支持的加密算法。 HTTPS 也不能防止网站被爬虫抓取,攻击者可以根据某些手段推测加密后的密文,从而使选择密文攻击成为可能。
Charles 为什么能抓 HTTPS 的包?
Charles 抓 HTTPS 包的过程可以理解为中间人攻击。
浏览器和服务器每次新建会话时都使用非对称密钥交换算法协商出对称密钥,也就是上文所说的 C_Key,使用 C_Key 完成应用数据的加解密和验证,整个会话过程中的密钥只在内存中生成和保存,而且每个会话的 C_Key 都不相同,并且无法窃取。
所以整个加密过程中,至关重要的就是客户端生成的对称秘钥 C_Key,中间人攻击是先伪装服务器向浏览器发送伪造的公钥,从而取得浏览器的私钥。这样就完成的浏览器端和服务器端的解密。
中间人攻击:是指攻击者与通讯的两端分别建立独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。
整个过程可以总结为以下:
(1) 首先代理软件截获浏览器发送给服务端的 HTTPS 请求,然后代理软件假装自己是浏览器向服务器发送请求进行握手。 (2) 代理软件获取服务器 CA 证书,验证 CA 证书并且解密后获取公钥 S_PuKey。 (3) 代理软件伪造 CA 证书,冒充服务器传递给客户端浏览器。浏览器解析 CA 证书,使用代理软件伪造的 S_PubKey 生成 C_Key。浏览器根据 C_Key 加密消息,并且计算 HASH,传递给代理软件。 (4) 代理软件根据私钥解析密文计算出浏览器的 C_Key,然后再使用服务端的公钥 S_PuKey 进行加密后返回给服务器。服务器用自己的私钥解开密文后与代理软件建立信任,握手完成。 (5) 代理软件获取服务器发送的密文,用对称秘钥解开,计算出服务器的明文(Charles 为什么能抓 HTTPS 的包?),再次加密后返回给浏览器。 (6) 整个通信过程中,代理软件一直拥有对称秘钥,因此整个 HTTPS 的过程中,信息始终对其透明。
综述:代理软件能够抓取 HTTPS 的核心是让浏览器信任代理软件的证书,使用这个证书代替要访问网站的证书。由于 CA 证书只能有特定的信任机构才能颁发,所以一般来说,中间人是无法欺骗浏览器获取信任的。而我们自己抓包则是主动信任了代理软件的证书,因此达到了使用代理软件可以抓取 HTTPS 的功能。
参考资料
- 超文本传输安全协议
- HTTPS那些事(一)HTTPS原理
- 中间人攻击