再探https与重放攻击
最近浏览到一篇关于https是如何防范重放攻击的文章,感兴趣的可以详细看下,文章中详细解释了其原理,但读完给我带来了一些疑惑——我们能否完全依赖https来防重放,进一步搜索,发现关于这个问题的说法不是很明确一致,于是决定在再探究下,便有了这篇文章。
本文将聚焦“我们能否完全依赖https来防重放”这个问题,尽可能做出准确的分析,同时也算提供验证资料准确性的一种参考。另外为了说明问题,会对相关概念、流程作以简述。
一、概念简介
1.1 https:是在http基础之上,引入TLS(安全传输层协议)/ SSL(安全套接层),利用其对数据包进行加密,保证两个应用间通信的保密性和可靠性,使客户与服务器应用之间的通信不被攻击者窃听。其中SSL最初由网景设计,并历经SSL1.0、SSL2.0、SSL3.0三个版本,之后由IETF将SSL标准化,并历经TSL1.0、TSL1.1、TSL1.2、TSL1.3等四个版本,目前市场主流使用版本是TSL1.2,截止到2021年TSL1.2之前版本都会被弃用。
1.2 重放攻击:是一种恶意或欺诈的重复或延迟有效数据的网络攻击形式。 可以由发起者或由拦截数据并重新传输数据的中间人来执行,其是“中间人攻击”的一个较低级别版本。
以上结合wiki对相关概念进行了简介,这里要说明下,我们这里讨论的重放攻击主要指中间人窃取数据这种场景,暂不考虑由发起者重复提交、CSRF等场景。
二、https流程及对于重放攻击的支持
这部分简单引用上述文章中对于https流程及防重放的解释说明。
2.1 https加密流程
(1)客户端生成一个随机数client_random,TLS版本号,发送到服务端。
(2)服务端发送自己的随机数server_random,服务器使用的证书,发送到客户端。
(3)客户端利用CA公钥对证书进行验证,取出服务器公钥。
(4)客户端生成随机数pre_master_secret,利用服务器公钥进行加密,传送到服务端。
(5)服务端利用服务器私钥进行解密取出pre_master_secret。
(6)服务端和客户端此时利用随机数client_random,server_random,pre_master_secret算出master_secret(主密钥)。
(7) 使用master_secret等参数,依照下面公式生成key_block(会话密钥)。
key_block = PRF(master_secret,"key expansion",server_random +client_random)
(8) 使用key_block 生成3对、6个密钥用来加密消息,以及生成MAC验证码,来保证消息完整性,MAC的公式如下:
2.2 防重放
MAC计算公式中存在seq_num参数,即数据的序列号,利用其进行累加,即可防范同一个链接下的重放攻击,对于不同链接由于client_random、server_random等参数不同,最终生成的对称密钥不同,也无法实现重放攻击。
三、我们是否可以依赖https
下面我们来验证上面的分析过程,上面的分析参考了TLS1.0,先来看下。
我们发现RFC文档中有这样一段与重放攻击相关的描述,可以看出大体流程与上文分析基本一致,上文分析过程参考了TLS1.0,由于TLS1.0是一个较旧的版本,且之前就听说过TLS1.3做了大量的改造,我们来看下其他版本是否也有一样的描述,经过验证TLS1.1、1.2描述基本一致,但TLS1.3中已经发生了变化。
根据图片中这部分说明,关注到2个问题,下面分别看下这两个问题:
1、TLS1.3在开启0-RTT时已经不提供关于重放攻击的支持。
这里简单解释下0-RTT, 0-RTT是TLS1.3中,针对于断线重连的场景,效率上的一个优化,其通过算法省去了之前重连中需要重新client-hello、server-hello的过程,详情点击,总之我们这里知道TLS1.3中如开启0-RTT则不提供重放攻击的防护。
2、由于客户端重试的存在,虽然原先就可能存在重放攻击,但0-RTT加重了这种问题。
这个问题我们重点关注之前的TLS版本是否确实存在这个问题,这里引用一篇谷歌研究员早先的文章,详情点击,依据这篇文章简单总结下针对TLS1.3之前版本的重放攻击方式。
1)、攻击者处于客户端与服务器之间的中继节点。
2)、攻击者检测到要重放的请求,转发给服务器,但不会把服务器response返回给客户端,而是断开与客户端的链接。
3)、客户端重试,并重新发送请求数据,攻击者转发请求到服务器。
这种攻击方式主要利用了客户端重试机制(在浏览器中普遍存在),在链接恢复过程中,产生了新的key_block(会话密钥),从而MAC值必然不会与之前重复,从而实现重放攻击。
四、结论及后记
结论:
通过上面的分析可以看出,https在一定程度上提供了重放攻击的防护,但并不足以让我们完全依赖https,此外对于服务端,https验证一般都在负载均衡之前就已经完成,内网间转发很可能是直接使用http,再者考虑重复提交、csrf等问题的防护手段与防重放有很多共通之处,我们还是应该从应用层去解决问题,具体解决方式资料已经很多,这里不再赘述。
后记:
网上很多资料的都受到作者的理解、读者的理解、应用的范围、知识的实效等诸多问题的影响(当然也包括本文),做出自己对于知识准确性的验证必不可少,对于一些简单功能性场景,可以通过编写测试代码进行验证,而对于不好验证的场景,通过官方文档结合一些高质量的英文资料相对更准确一些,简单来说对于工程开发类的资料,信息转发的次数愈少通常越准确,欢迎交流指正。
再探https与重放攻击
最近浏览到一篇关于https是如何防范重放攻击的文章,感兴趣的可以详细看下,文章中详细解释了其原理,但读完给我带来了一些疑惑——我们能否完全依赖https来防重放,进一步搜索,发现关于这个问题的说法不是很明确一致,于是决定在再探究下,便有了这篇文章。
本文将聚焦“我们能否完全依赖https来防重放”这个问题,尽可能做出准确的分析,同时也算提供验证资料准确性的一种参考。另外为了说明问题,会对相关概念、流程作以简述。
一、概念简介
1.1 https:是在http基础之上,引入TLS(安全传输层协议)/ SSL(安全套接层),利用其对数据包进行加密,保证两个应用间通信的保密性和可靠性,使客户与服务器应用之间的通信不被攻击者窃听。其中SSL最初由网景设计,并历经SSL1.0、SSL2.0、SSL3.0三个版本,之后由IETF将SSL标准化,并历经TSL1.0、TSL1.1、TSL1.2、TSL1.3等四个版本,目前市场主流使用版本是TSL1.2,截止到2021年TSL1.2之前版本都会被弃用。
1.2 重放攻击:是一种恶意或欺诈的重复或延迟有效数据的网络攻击形式。 可以由发起者或由拦截数据并重新传输数据的中间人来执行,其是“中间人攻击”的一个较低级别版本。
以上结合wiki对相关概念进行了简介,这里要说明下,我们这里讨论的重放攻击主要指中间人窃取数据这种场景,暂不考虑由发起者重复提交、CSRF等场景。
二、https流程及对于重放攻击的支持
这部分简单引用上述文章中对于https流程及防重放的解释说明。
2.1 https加密流程
(1)客户端生成一个随机数client_random,TLS版本号,发送到服务端。
(2)服务端发送自己的随机数server_random,服务器使用的证书,发送到客户端。
(3)客户端利用CA公钥对证书进行验证,取出服务器公钥。
(4)客户端生成随机数pre_master_secret,利用服务器公钥进行加密,传送到服务端。
(5)服务端利用服务器私钥进行解密取出pre_master_secret。
(6)服务端和客户端此时利用随机数client_random,server_random,pre_master_secret算出master_secret(主密钥)。
(7) 使用master_secret等参数,依照下面公式生成key_block(会话密钥)。
key_block = PRF(master_secret,"key expansion",server_random +client_random)
(8) 使用key_block 生成3对、6个密钥用来加密消息,以及生成MAC验证码,来保证消息完整性,MAC的公式如下:
2.2 防重放
MAC计算公式中存在seq_num参数,即数据的序列号,利用其进行累加,即可防范同一个链接下的重放攻击,对于不同链接由于client_random、server_random等参数不同,最终生成的对称密钥不同,也无法实现重放攻击。
三、我们是否可以依赖https
下面我们来验证上面的分析过程,上面的分析参考了TLS1.0,先来看下。
我们发现RFC文档中有这样一段与重放攻击相关的描述,可以看出大体流程与上文分析基本一致,上文分析过程参考了TLS1.0,由于TLS1.0是一个较旧的版本,且之前就听说过TLS1.3做了大量的改造,我们来看下其他版本是否也有一样的描述,经过验证TLS1.1、1.2描述基本一致,但TLS1.3中已经发生了变化。
根据图片中这部分说明,关注到2个问题,下面分别看下这两个问题:
1、TLS1.3在开启0-RTT时已经不提供关于重放攻击的支持。
这里简单解释下0-RTT, 0-RTT是TLS1.3中,针对于断线重连的场景,效率上的一个优化,其通过算法省去了之前重连中需要重新client-hello、server-hello的过程,详情点击,总之我们这里知道TLS1.3中如开启0-RTT则不提供重放攻击的防护。
2、由于客户端重试的存在,虽然原先就可能存在重放攻击,但0-RTT加重了这种问题。
这个问题我们重点关注之前的TLS版本是否确实存在这个问题,这里引用一篇谷歌研究员早先的文章,详情点击,依据这篇文章简单总结下针对TLS1.3之前版本的重放攻击方式。
1)、攻击者处于客户端与服务器之间的中继节点。
2)、攻击者检测到要重放的请求,转发给服务器,但不会把服务器response返回给客户端,而是断开与客户端的链接。
3)、客户端重试,并重新发送请求数据,攻击者转发请求到服务器。
这种攻击方式主要利用了客户端重试机制(在浏览器中普遍存在),在链接恢复过程中,产生了新的key_block(会话密钥),从而MAC值必然不会与之前重复,从而实现重放攻击。
四、结论及后记
结论:
通过上面的分析可以看出,https在一定程度上提供了重放攻击的防护,但并不足以让我们完全依赖https,此外对于服务端,https验证一般都在负载均衡之前就已经完成,内网间转发很可能是直接使用http,再者考虑重复提交、csrf等问题的防护手段与防重放有很多共通之处,我们还是应该从应用层去解决问题,具体解决方式资料已经很多,这里不再赘述。
后记:
网上很多资料的都受到作者的理解、读者的理解、应用的范围、知识的实效等诸多问题的影响(当然也包括本文),做出自己对于知识准确性的验证必不可少,对于一些简单功能性场景,可以通过编写测试代码进行验证,而对于不好验证的场景,通过官方文档结合一些高质量的英文资料相对更准确一些,简单来说对于工程开发类的资料,信息转发的次数愈少通常越准确,欢迎交流指正。