前言
近年来,几乎所有网站都开始使用https协议,那么https究竟是什么,它与http相比有什么优缺点?其底层原理又是怎么样的?https一定安全吗?
本文将从http的安全讲起,分析和改进通信方式,由浅入深,逐步引出https,然后梳理https流程,并总结一些个人对于https安全的思考。
1. http的安全问题
HTTP协议由于是明文传送,所以存在三大风险:窃听、篡改、冒充。
冒充:攻击者通过dns劫持,社会工程学(例如:共享免费热点)等攻击手段,使客户端访问某个常规网站的请求实际发送给伪装服务器,客户端并不感知。对于测试环境,一些抓包工具就可以实现。 窃听:由于是明文传输,伪装服务器可以轻易窃听所有数据,通过数据分析手段,提取出密码信息也不难。
伪装服务器可以选择仅窃听,将客户端的请求原样转发给真实服务器,收到响应消息后,将消息原样返回给客户端,此情况下,客户端不感知攻击者的存在。篡改:伪装服务器还可以选择篡改真实服务器的响应消息,将伪造的数据返回给客户端。
上图示例就是将返回消息”OK”修改为”OK, 123!”返回给客户端。
https就是为了解决上述三个风险而设计的。
下面我们通过逐步改进http的通信方式,分析如何安全的进行消息通信。
2. A如何把消息安全的发送给B
2.1 方案1:使用对称加密
对称加密,简单理解就是使用同一个密钥对明文进行加密和解密。
下图是A和B使用对称加密通信的流程图: 此方案乍一看没有问题,只要密钥不被第三者知道,攻击者就无法拿到明文。
在C/S架构中,A和B可以在安装部署时约定好一个密钥,只要密钥不经过网络传输,不考虑A和B本身受攻击的情况,攻击者仅通过网络窃听抓包是做不了什么的。
但是在B/S架构中呢?浏览器是用户自己装的,没有机会和服务器商量密钥。即使能商量,浏览器不可能预置全球所有服务器的密钥。即使预置了,浏览器是任何人都可以下载安装的,密钥谁都可以拿到,没有保密可言。总而言之,在B/S架构中,想双方事先商量好一个密钥来使用是行不通的。
那能不能密钥由一方生成,通过网络发送给另一方呢? 这显然也是不行的,密钥只要经过网络发送,就有可能被窃取。
我们需要继续改进方案,这就引出了我们下面要讲的RSA非对称加密。
2.2 方案2:使用RSA非对称加密
非对称加密的具体原理网上有很多,这里不详细描述。
我们只要知道两个概念:
非对称加密需要两个密钥
我们假设记作:e, de加密的内容,只有d能解密 d加密的内容,只有e能解密。 仅有e无法推导出d,仅有d也无法推导出e。(严格的讲,不是无法推导出,而是计算量很大,目前人类的计算机需要执行很长时间才能计算出来,可能是几十年,上百年。随着量子计算机的发展,或许有一天只要一周就能计算出结果,那时整个互联网安全体系都将不再安全)
公开出去的密钥叫公钥,保密的叫私密
e和d是对等的,我们可以任意选择一个做公钥,另一个做私钥。
了解上面的概念后,我们来看一下A和B如何利用非对称加密通信: 从图中可以看出,相较于对称加密,非对称加密不需要A事先预置各个服务器的密钥,只需要在请求服务时,向该服务请求获取一个公钥即可,公钥本身就是公开的,可以在网络中传输。A拿到公钥后将明文加密发送给B。由于私钥只有B才有,所以攻击者即使窃听到A发送的密文也无法解密。如此,A发送的消息就安全到达B了。
然而,这样真的就安全了吗?
如果攻击者只是窃听网络,这么做确实安全了,因为在网络中传输的只有公钥和A加密后的密文,这个密文只有B的私钥能解密。所以攻击者拿不到有用的信息 但是,攻击者仍然可以通过冒充对端的方式实现攻击,如下图: 攻击者通过一些手段,使A以为攻击者就是B,从而骗过A获取到明文。
由此可见,上述方式使用非对称加密依然不安全,这就引出下文要讲的内容。
3. A如何确认自己访问的B是真正的B
现在出现一个新问题:A如何确认自己访问的B是真正的B?请B证明自己是B。
我们思考一下,在人类社会,要确认一个人的身份,可以要求他出示身份证,并且我们有能力确认身份证是不是伪造的。这个身份证是由个人向第三方(派出所)申请的,不是由个人自己制作的。只要出示了自己的身份证,就可以证明自己是自己。
在网络的世界里,我们也需要引入一个第三方机构,也就是我们常常听说的CA机构,此机构专门给申请者颁发证书(身份证): 观察图中的四步流程,我们思考每一步可能出现的问题:
B申请的证书内容是什么?如何保证不会被伪造? A要求B出示证书,假如这个B是攻击者冒充的,他也向CA申请一个合法证书,再返回这个证书给A不行吗?这样A即使拿着证书去验证,也发现不了问题,因为证书是合法的。 B返回证书给A时,不会被篡改吗?这个其实和问题1是一样的。 A去CA机构验证证书真假,攻击者会不会冒充CA呢?
假如上面的问题都得以解决,那么就解决了“A如何确认自己访问的B是真正的B”的问题。
下面我们逐步分析。
3.1 B向CA申请的证书是什么
3.1.1 CA机构做了什么
CA机构自己使用非对称加密算法,生成了一对私钥和公钥。这个私钥由CA机构确保绝对不会泄露。 CA机构又制作了一个根证书,里面明文保存了机构名称、CA公钥等信息。根证书会预置在各个厂家的浏览器中(对于本文的示例,即预置在A中),我们认为根证书是安全的,里面的内容是可信的(这也是为什么我们不要随便给浏览器导入未知来源的根证书)。
3.1.2 CA机构如何给B签发证书
CA又生成一对私钥和公钥给B使用 B的私钥由B保密存储 B的公钥明文存储在B的证书中 CA对B的证书中的明文内容计算一个哈希值,同时使用CA的私钥加密,得到B的证书的签名。 至此,B获得2个文件:B的私钥文件、B的证书文件。
3.2 A收到B返回的证书,如何确认未被攻击者修改
A对B的证书中的明文内容计算一次哈希值得到Hash1 A查看B的证书的签发者,发现是XXX_CA根证书,于是去此根证书中拿到根证书的公钥 A使用根证书的公钥对B证书的签名解密,得到明文哈希值Hash2 比较Hash1和Hash2相等,说明证书未被修改。
为什么这样就能确认证书未被修改?
前文提到,B的证书签名是由CA私钥加密的,只有CA的公钥能解密。假如攻击者修改了明文内容,由于攻击者没有CA的私钥,所有无法重新生成签名;假如攻击者使用自己生成的私钥来签名,那么A在使用CA的公钥(此公钥是预置的,不经过网络,攻击者无法修改此公钥)来解密签名时就会失败,因为这样公钥和私钥不配套。
所以,A通过此方法,就可以确认B返回的证书是。
3.3 A确认证书未被修改之后,如果确认对方不是冒充的B
A查看B的证书中的域名,是否是A要访问的域名,如果不是,说明可能被攻击了,停止访问。
3.3.1 思考1:攻击者难道不可以向CA申请一个合法证书,里面的域名就是B的域名,然后再冒充B和A通信?
其实大家去实际申请一次证书就知道了:在向CA申请证书时,一般要根据CA机构的提示,将一段cname文本添加到域名DNS解析中。什么意思?就是CA要你证明,你是这个域名的拥有者,你有权限登录域名后台管理修改配置。
总之,除非攻击者有你的域名权限,否则他申请不到合法的包含此域名信息的证书。
3.3.2 思考2:B的证书是谁都可以拿到的,攻击者就拿B的证书放到自己服务器,再冒充成B与A通信,是否可行?
攻击者固然可以把B的证书放到自己的服务器返回给A,此时A检验此证书是合法的。 但是,我们还有一个东西没有用到,那就是B的私钥。由于这个私钥是B保密存储的,不经过网络,攻击者获取不到。 A在检验证书合法之后,将会使用证书中的公钥来加密一些内容发送给B,与B协商后续流程。 正常情况,既然内容是用公钥加密的,那么B可以用私钥来解密查看。 攻击者如果冒充B,当A发送此内容过来时,由于攻击者拿不到B的私钥,无法解密A的协商内容,将会导致协商失败。具体协商流程这里不做展开。
总之,攻击者要想冒充B与A通信,必须拿到B的私钥才能实现。
3.4 对于https安全的注意事项总结
通过前文的分析,我们可以看到,https也不是绝对安全的,需要注意以下事项:
对于CA机构,不要泄露CA的私钥。所以一般不使用根证书来签发用户证书,而是先生成一个子CA证书,再由子CA证书签发用户证书。 对于客户端,不要随便导入未知来源的根证书。 对于服务端,不要泄露申请证书时获得的私钥。 整个数字证书的机制,只是为了防止攻击者从网络入手,例如窃听、篡改、冒充等。如果攻击者使用病毒传播、主机漏洞等方式,直接攻击到服务器或者客户端主机,数字证书是无法防范的。这也是为什么抓包工具可以对https协议进行抓包可查看内容,因为我们对机器有足够的权限。