HTTPS中间人攻击,HTTPS被抓包了怎么办?
目录
二、什么是中间人攻击
三、https 是绝对安全的吗
四、中间人攻击的初步了解
五、中间人攻击的深入了解
六、https 是如何防止中间人攻击的
SSL-Pinning
七、浏览器是如何确保CA证书的合法性?
(1)证书包含什么信息?
(2)证书的合法性依据是什么?
(3)浏览器如何验证证书的合法性?
八、https 可以抓包吗
九、预置证书/公钥更新问题
一、写在前面
首先,当个位读者在看到这篇文章时,我默认大家已经对HTTPS协议有一定的了解,包括但不仅限于了解HTTSP和HTTP的区别以及HTTPS建立连接的过程,如果你不懂这些,希望你能花一些时间先去了解我说的这些。
二、什么是中间人攻击
中间人攻击是指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。
HTTPS 使用了 SSL 加密协议,是一种非常安全的机制,目前并没有方法直接对这个协议进行攻击,一般都是在建立 SSL 连接时,拦截客户端的请求,利用中间人获取到 CA证书、非对称加密的公钥、对称加密的密钥;有了这些条件,就可以对请求和响应进行拦截和篡改。
三、https 是绝对安全的吗
不是绝对安全的,可以通过中间人攻击。
四、中间人攻击的初步了解
过程原理:
- 本地请求被劫持(如DNS劫持等),所有请求均发送到中间人的服务器
- 中间人服务器返回中间人自己的证书
- 客户端创建随机数,通过中间人证书的公钥对随机数加密后传送给中间人,然后凭随机数构造对称加密对传输内容进行加密传输
- 中间人因为拥有客户端的随机数,可以通过对称加密算法进行内容解密
- 中间人以客户端的请求内容再向官方网站发起请求
- 因为中间人与服务器的通信过程是合法的,官方网站通过建立的安全通道返回加密后的数据
- 中间人凭借与官方网站建立的对称加密算法对内容进行解密
- 中间人通过与客户端建立的对称加密算法对官方内容返回的数据进行加密传输
- 客户端通过与中间人建立的对称加密算法对返回结果数据进行解密
由于缺少对证书的验证,所以客户端虽然发起的是 HTTPS 请求,但客户端完全不知道自己的网络已被拦截,传输内容被中间人全部窃取。
五、中间人攻击的深入了解
首先,在客户端和服务端建立HTTPS连接的初期,客户端和服务端双方发生了经历的以下过程
而中间人在这个过程中可以做什么事情呢?我们还以Fiddler举例。Fiddler的工作是介于客户端和服务器中间的,它会先于客户端接收到服务器返回的加密数据,然后它也可以使用操作系统内置的CA公钥对这段数据解密,从而得到服务器的公钥,并先将这个公钥保存起来。
接下来,Fiddler会将解密出来的数据进行调包,将其中服务器返回的公钥替换成自己的一个公钥,然后使用自己的非对称加密的私钥对数据重新加密,并将这段重新加密后的数据返回给客户端。示意图如下:
但是我们知道,用Fiddler自己的私钥加密后的数据,客户端肯定解密不出来呀,因为Fiddler的公钥并没有内置到客户端操作系统当中,所以我们一定要在手机上安装一个Fiddler提供的证书才行,只是为了让客户端能够解密出Fiddler调包之后的数据。如下图所示:
这样客户端仍然获得了一个公钥,并且还以为这个公钥是服务器返回的,实际上这是一个被Fiddler调包之后的公钥。而服务器返回的真实公钥则被Fiddler保存了起来。
到这里为止,获取服务器公钥的流程就结束了,目前各部分的状态如下:
接下来是客户端与服务器商定对称加密密钥的过程。
客户端可以利用随机算法在本地生成一个对称加密密钥,并用服务器返回的公钥进行加密,然后发送给服务器。由于公钥加密的数据只能用私钥解密,因此没有任何人能破解出客户端生成的对称加密密钥到底是什么。
然后服务器这边使用自己的私钥将客户端发来的数据进行解密,这样客户端和服务器就都知道对称加密的密钥是什么了,并且绝对没有第三个人能知道,这样双方之后都使用对称加密来进行通讯即可,从而保证了数据传输的安全。示意图如下:
然而现在有了Fiddler,一切就都不一样了。
客户端这边拿到的其实根本就不是服务器的公钥,而是由Fiddler调包后的公钥。所以,客户端这边生成一个对称加密密钥后,使用的也是Fiddler调包后的公钥来进行加密的,这样这段加密后的数据只有用Fiddler自己的私钥才能解开。
那么很显然,Fiddler当然是有自己的私钥的,因此它能够解密出这段数据,这样Fiddler就知道客户端生成的对称加密密钥是什么了。
接下来不要忘记,Fiddler还在之前就保存了服务器返回的真实公钥,那么现在Fiddler可以用真实的服务器公钥再次加密这段数据,然后将加密后的数据发送给服务器。
对于服务器而言,它并不知道客户端这边发生了什么事,也不知道Fiddler的存在。它只知道,用自己的私钥是可以解密出客户端发来的数据,并能从中获得对称加密的密钥。示意图如下:
到这里,对称加密密钥的商定过程也就结束了,目前各部分的状态如下:
你会发现,现在客户端、服务器、Fiddler,这三者都知道对称加密的密钥是什么。
之后客户端与服务器之间的所有通讯都会使用这个密钥加密后再进行传输,不知道密钥的人自然是无法解密出传输的内容的,但是Fiddler却知道密钥是什么,因此它可以完美监听客户端与服务器之间的通讯内容,也就实现了对https协议抓包的功能。
以上就是https协议抓包的实现原理,虽然从最后的结果看上去,Fiddler在其中各种调包替换数据,干了很多不安全的操作。但Fiddler之所以有权限这么干,前提因为我们在一开始的时候手动安装了Fiddler的证书,否则后面的流程都是走不通的。
六、https 是如何防止中间人攻击的
https 无法防止中间人攻击,只有做证书固定ssl-pinning 或者 apk中预置证书做自签名验证可以防中间人攻击。具体的可以看这一篇文章。
SSL-Pinning
- 证书锁定(Certificate Pinning)
在客户端代码内置仅接受指定域名的证书,而不接受操作系统或浏览器内置的CA根证书对应的任何证书。(缺陷:证书有效期问题) - 公钥锁定(Public Key Pinning)
提取证书中的公钥并内置到客户端中,通过与服务器对比公钥值来验证连接的正确性
七、浏览器是如何确保CA证书的合法性?
(1)证书包含什么信息?
颁发机构信息、公钥、公司信息、域名、有效期、指纹......
(2)证书的合法性依据是什么?
首先,权威机构是要有认证的,不是随便一个机构都有资格颁发证书,不然也不叫做权威机构。另外,证书的可信性基于信任制,权威机构需要对其颁发的证书进行信用背书,只要是权威机构生成的证书,我们就认为是合法的。所以权威机构会对申请者的信息进行审核,不同等级的权威机构对审核的要求也不一样,于是证书也分为免费的、便宜的和贵的。
(3)浏览器如何验证证书的合法性?
浏览器发起HTTPS请求时,服务器会返回网站的SSL证书,浏览器需要对证书做以下验证:
- 验证域名、有效期等信息是否正确。证书上都有包含这些信息,比较容易完成验证;
- 判断证书来源是否合法。每份签发证书都可以根据验证链查找到对应的根证书,操作系统、浏览器会在本地存储权威机构的根证书,利用本地根证书可以对对应机构签发证书完成来源验证;
- 判断证书是否被篡改。需要与CA服务器进行校验;
- 判断证书是否已吊销。通过CRL(Certificate Revocation List 证书注销列表)和 OCSP(Online Certificate Status Protocol 在线证书状态协议)实现,其中 OCSP 可用于第3步中以减少与CA服务器的交互,提高验证效率。
以上任意一步都满足的情况下浏览器才认为证书是合法的。
八、https 可以抓包吗
HTTPS 的数据是加密的,常规下抓包工具代理请求后抓到的包内容是加密状态,无法直接查看。
但是,我们可以通过抓包工具来抓包。它的原理其实是模拟一个中间人。通常 HTTPS 抓包工具的使用方法是会生成一个证书,用户需要手动把证书安装到客户端中,然后终端发起的所有请求通过该证书完成与抓包工具的交互,然后抓包工具再转发请求到服务器,最后把服务器返回的结果在控制台输出后再返回给终端,从而完成整个请求的闭环。
有人可能会问了,既然 HTTPS 不能防抓包,那 HTTPS 有什么意义?
HTTPS 可以防止用户在不知情的情况下通信链路被监听,对于主动授信的抓包操作是不提供防护的,因为这个场景用户是已经对风险知情。要防止被抓包,需要采用应用级的安全防护,例如采用私有的对称加密,同时做好移动端的防反编译加固,防止本地算法被pojie。
九、预置证书/公钥更新问题
这样做虽然解决了抓包问题,但是也带来了另外一个问题:我们购买的证书都是有有效期的,到期前需要对证书进行更新。主要有两种方式:
- 提供预置证书更新接口。在当前证书快过期时,APP请求获取新的预置证书,这过渡时期,两个证书同时有效,直到安全完成证书切换。这种方式有一定的维护成本,且不易测试。
- 在APP中只预埋公钥,这样只要私钥不变,即使证书更新也不用更新该公钥。但是,这样不太符合周期性更新私钥的安全审计需求。一个折中的方法是,一次性预置多个公钥,只要任意一个公钥验证通过即可。考虑到我们的证书一般购买周期是3-5年,那么3个公钥,可以使用9-15年,同时,我们在此期间还可以发布新版本废弃老公钥,添加新公钥,这样可以使公钥一直更新下去。
YancyPeng: 其实中间人根本不需要篡改公钥啊,获取到服务器的公钥之后,岂不是可以代替客户端进行通信?并且可以把客户端本身发送的消息全部丢弃(因为没有私钥解密不出来)
shot_gan: 关于第三部分-子网划分的方法中的“表4-6”里面的“子网数”似乎有错误。我认为不用减去2。理由如下: 子网数量的影响解释: 子网的数量本身并不会因为网络地址和广播地址而减少。但是,当考虑到最小的子网时(如一个子网只有4个地址),有效的主机地址确实很少。 理论与实际的子网数量: 例如,如果你有一个B类网络(假设网络地址为 172.16.0.0),使用子网掩码 255.255.255.192 进行子网划分: - 子网掩码为 255.255.255.192,对应的二进制为 11111111.11111111.11111111.11000000。 - 这意味着有2个子网位(因为192 = 11000000,有2个1),和6个主机位(因为剩下的6个0)。 理论上: 2个子网位可以划分出 2^2=4个子网。但是每个子网有一个网络地址和一个广播地址,不能用于分配给主机,因此每个子网的有效主机数量是:2^6−2=62个可用主机。 子网数量不受主机地址影响 所以,理论上有4个子网,每个子网有62个可用主机。每个子网的网络地址和广播地址仅影响每个子网的主机数量,而不会减少子网的数量。 例如,划分的子网和主机地址: A:子网1:172.16.0.0/26 网络地址:172.16.0.0 可用地址范围:172.16.0.1 - 172.16.0.62 广播地址:172.16.0.63 B:子网2:172.16.0.64/26 网络地址:172.16.0.64 可用地址范围:172.16.0.65 - 172.16.0.126 广播地址:172.16.0.127 C:子网3:172.16.0.128/26 网络地址:172.16.0.128 可用地址范围:172.16.0.129 - 172.16.0.190 广播地址:172.16.0.191 D:子网4:172.16.0.192/26 网络地址:172.16.0.192 可用地址范围:172.16.0.193 - 172.16.0.254 广播地址:172.16.0.255 综上所述: 每个子网有两个特殊的IP地址(网络地址和广播地址),这只影响到每个子网内部的可用主机数量,而不会影响到总的子网数量。
csdn_fruit: 好啊,有质量
Cc_347: 终于解决疑惑了
炸了噻: 提壶(bushi)灌顶