这是一个小品,专注于讨论一个对于初级开发者比较容易引起困惑的问题,就是在使用HTTP协议发起请求的时候,它的安全性应该如何考虑和看待?
之所以说容易引起困惑,是由于经常有很多似是而非的认知和说法,比如POST请求比GET请求要安全,HTTPS协议不能保证URL的安全等等。本文会尽力从原理和逻辑出发,清晰明确的破解这些迷思。
先说几个结论:
- 单纯的HTTP协议,没有安全性可言
- 如果使用HTTPS协议,可以保证内容的安全,包括URL内容的部分
- HTTPS协议并不完全安全,例如DNS解析过程,可能会泄漏一些信息
- HTTPS协议对于Web应用安全非常重要,是所有技术安全措施中最优先考虑的项目
我们下面逐步展开讨论这些结论和问题。
HTTP协议安全
先说第一个结论,单纯的HTTP协议本身,没有安全性可言。
因为本质上而言,HTTP协议就是TCP协议的应用层扩展。TCP协议本身并不解决信息传输安全的问题,所以原生的HTTP协议,也不提供网络和应用层面的安全(图为一个典型的HTTP请求的构成和内容,都是明文)。
为了更好的理解这一点,我们需要先了解一下在这个过程中,信息安全是如何被破坏的。
首先就是信息的机密性。TCP协议原生是没有加密机制的,传输的信息,就是原始信息的二进制编码的数据,而这些编码方案都是标准化和公开的,如ASCII,Unicode等等。只要攻击者能够在网络上截获相关的通信内容,就可以轻易的解码得到原始信息。而如果不使用专用网络,如互联网,由于网络传输的复杂性和开放性,发送者是无法保证传输的信息不被窃听或者复制的。
第二点就是信息的完整性。攻击者获取本应机密的信息是一类安全问题。如果他还有能力伪造和篡改原始信息,让接收者获得的不是完整和正确的信息,在很多时候会造成更大的破坏。通过前面的分析,我们也可以很容易的理解,TCP协议不能保证这一点。
然后就是信息的不可抵赖性,就是接收方可以完全的确定信息的来源就是发送方,这在很多业务上也是一个明确的信息安全要求,用于进行授权和确认,防止假冒的信息主体。这通常只能通过密码学中的签名和验证机制完成。显然,原始的TCP协议也无法做到这一点。
所以,我们可以看到,TCP协议主要解决信息传输的问题,本身并没有信息安全方面的考量和设计。其实从逻辑上而言,那确实是应该在更高的层次如会话层或者应用层的问题,而不是网络层的问题。
这时,如果需要保证应用层面的安全,可以有三个选择:
- 基础网络协议(TCP/IP)
直接在网络协议层面上提供安全性,如IPSec、VPN等等,保护所有的基础网络通信,这确实有一定的适用场景如企业应用,但显然不适合于如互联网这种完全的开放网络,因为涉及到大规模的认证、授权、控制等等,技术和实现上就过于复杂了。
- 应用程序实现(Application)
可以通过对应用传输的数据进行加密,这就是在应用层面上实现信息安全。这需要应用程序自己开发相关的信息安全协议和应用实现,如加密解密、签名验证算法等等。这个处理方法,显然代价比较高昂,也没有很好的通用性和可扩展性。
- HTTP协议扩展
就是对HTTP协议本身进行扩展,在协议层面上提供安全性,这也是现在应用最为广泛的主流技术方案,即HTTPS协议。这样的扩展在逻辑上是和应用无关的。就像集装箱运输一样,无论你需要运什么货,都可以先装到集装箱里面,而集装箱本身是标准化的,可以在不同的运输系统和工具如轮船、火车和货车系统间一致和高效的处理。
相关的细节,我们后面会深入探讨。
HTTPS协议安全
简单而言,HTTPS协议,就是基本的HTTP协议加上一个信息安全协议(SSL或者TLS)。从语义和应用方式上而言,并没有改变HTTP协议的应用规范(就是文本信息和指令),但通过在传输时,使用一些安全协议和规范对其进行了相关的安全处理,来保证传输过程的安全,从而实现了应用层面的安全。
HTTPS所使用的安全协议套件和实现,也是有一个发展的过程的,早期的设计,基于兼容和扩展的考虑,可以支持多种具体的实现。现在HTTPS协议主流的安全套件是TLS1.3版本,在2018年发布,现在大多数主流操作系统和浏览器软件都已经支持,也是现在Web应用系统优先使用的版本。比如下图为bing页面所使用的HTTPS的TLS版本和设置,我们可以看到它使用了TLS1.3的版本,并且安全设置字符串显示了它使用了AES-256-GCM对称加密算法和SHA384摘要算法,密钥长度256bit。
关于HTTPS协议的工作原理和技术细节,我们在这里不会过于深入的探讨。我们只需要了解,HTTPS在连接过程中分为TCP连接和TLS安全协商两个阶段(下图),并且在传输过程中,可以对HTTP的内容进行加密传输,同时可以通过证书和公私钥机制,来保证信息的完整性,和实体安全就可以了。理解了这些内容,对于我们后面的一些疑问的明析和解答,应该就已经够用了。
问题和分析
在了解了HTTP协议相关的内容和原理之后,我们就可以尝试使用相关的知识,来回答一些我们在日常工作中遇到的Web应用安全方面的问题了。
- Post比Get更安全?
从协议使用的角度而言,无论是Post操作还是Get操作,只有语义的意义。Post和Get,都是HTTP数据包的内容,只不过Post内容会附加在请求数据的后面。这里,所有相关的指令和数据的传输安全性,都是由协议来保证的,所以它们在真正的信息安全的角度而言,是没有差异的。
唯一的差别,就是在使用的时候,Get请求的内容,可能是会显示在浏览器的地址栏中;而Post的内容,除了URL地址外,还有一部分是在表单中,有可能不可见。这里的差异和安全,只是一种心理感受。因为绝大部分攻击者,都是在网络中远程发起攻击和破坏,绝对不会坐在用户后面来偷窥用户的屏幕。所以这个感受,就仅仅是感觉而已。
同样的道理,可以这样讲,所有的HTTP方法,在安全性方面,其实都是一样的。
- HTTPS的URL地址安全吗
应该这样讲,一部分安全。主机名和IP地址不安全,但后面的内容,就是请求路径这部分是安全的。我们只讨论URL这一部分。
当我们使用浏览器,在地址行中输入并确认一个URL地址的时候,在默认情况下,它会首先使用操作系统的DNS解析机制,来获取这个域名所对应的IP地址,这时候使用的其实是DNS协议,通常(后面会解释为什么是通常)由操作系统的相关网络模块来负责这个部分的操作。DNS协议本身也是不安全的,它基本上无条件的信任由所配置的DNS服务器提供的信息,从而获得一个IP地址。
然后,浏览器会尝试使用TCP协议,来连接这个IP地址对应的主机系统,并执行HTTP协议相关的操作。这个连接请求的过程,也是不安全的,就是第三方可能可以通过分析网络流量,来获知某个用户试图连接一个IP地址来发起HTTP请求。
TCP连接建立之后,如果是使用HTTPS协议,则随后就会进入TLS的连接协商过程,这个过程完成之后,才会真正的发送HTTP指令和信息,这些信息已经可以受到安全协议的保护了。URL的后面部分,就是路径部分,当然也会受到保护,所以,网络流量的侦听者,是无法解码这部分内容的。
- HTTP内置的认证机制安全吗?
应该这样讲,如果使用HTTP协议,基本不安全。但如果改进为使用HTTPS协议,安全性可以大大提高。HTTP内置的认证机制分为基本认证和摘要认证两个标准,BaseAuth使用Base64对认证信息进行编码,而Digest使用MD5对密码进行编码,这两种方式都不能有效的保证信息的机密性。在认证阶段,HTTP通过在请求头中的Authorization字段,来标识和控制认证过程,这个内容,其实也是HTTP传输内容的一部分。所以如果使用HTTPS协议,这部分的内容传输是可以受到保护的,基本上可以认为是安全的。
笔者不太理解,为什么后来没有在基本认证规范的基础上,再提出更先进和安全的认证规范,比如说使用加盐的SHA摘要等等,也许是有了OAuth这种更安全和集成性更好的机制,本地认证的必要性不大的原因吧。
- 使用Cookie保持授权信息安全吗?
简单来讲,在HTTP协议中,使用Cookie来保存认证信息,作为授权和访问控制的依据,是不安全的。而在HTTPS协议中,是安全的。原理很简单,Cookie在HTTP规范中,是使用HTTP头信息实现的,它是HTTP请求和响应数据的一部分。
同样的原理,对于HTML中的表单的处理,在安全性方面也是类似的。
小结
本文通过结合HTTP和HTTPS协议的基本工作原理,分析了各种实际操作涉及到的过程和场景,它们在安全性方面的影响和问题。最后,我们也可以基本得到一个比较确定的结论,就是HTTPS协议的部署和使用,可以极大的增强Web应用系统的安全性,是所有Web应用安全的一个基础和最优先考虑的实现方案。所以,google才会力推互联网的全面HTTPS化。