fnmstd@这里是河马
最近拜读了《CDN Backfired: Amplification Attacks Based on HTTP Range Requests》这篇由清华大学主导的DSN2020最佳论文,做一个简单的笔记。
论文下载地址:
https://netsec.ccert.edu.cn/files/papers/cdn-backfire-dsn2020.pdf
此处先膜一下各位论文作者,tql~
首先是两个概念,了解的可以直接跳过:
CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。
目前主要形式还是以反向代理,产品有很多CloudFlare、AWS的CloudFront;阿里云、腾讯云的CDN产品;云WAF也基本上都带有CDN功能。
单独说一下CDN缓存:
当服务接入了 CDN 之后,浏览器本地缓存的资源过期之后,浏览器不是直接向源服务器请求资源,而是转而向 CDN 边缘节点请求资源。CDN 边缘节点中将用户的数据缓存起来,如果 CDN 中的缓存也过期了,CDN 边缘节点会向源服务器发出回源请求,从而来获取最新资源。
一些CDN的缓存可以通过加请求参数、更改请求头等等方法,令已缓存的资源资源被认为未缓存,进而令CDN回源站进行读取。
HTTP 协议范围请求允许服务器只发送 HTTP 消息的一部分到客户端。范围请求在传送大的媒体文件,或者与文件下载的断点续传功能搭配使用时非常有用。
所以,Range请求主要用途:大文件分块下载、断点续传、多线程下载
可以使用HEAD请求(GET也可以,只是会返回响应内容),确认所请求资源是否支持Range,如下图所示,包含Accept-Ranges为bytes为支持:
不包含Accept-Ranges头,或Accept-Ranges值为none则不可用(不排除有别的值,目前看是只有bytes和none)。
使用Range请求时,需要在HTTP请求头中加入Range头,Range头的形式有两种:
单一范围:
Range: bytes=0-1023
带上述请求头的请求返回0-1023个字节,服务器端会返回状态码为 206
Partial Content
的响应,响应内容为我们所请求的1024字节的内容。
多重范围,用于请求多个数据块(范围可重叠,后面的ORB手法就是利用重叠的范围进行攻击)
Range: bytes=0-50, 100-150
带有多重范围Range请求的请求,服务器会返回 206
Partial Content
状态码,同时使用类似文件上传时的multipart多重分块作为响应(Content-Type为multipart/byteranges),下面使用boundary进行分割多块内容。
论文中整理了CDN在处理Range请求时的回源策略有如下三种(详见原论文中Table I/Table II):
懒惰型:不做任何改变,直接转发带Range头的请求
删除型:直接删除Range头再转发
扩展型:将Range头扩展到一个比较大范围
其中删除型
及扩展型
是CDN缓存为了增加缓存命中率而做的优化,对于Range请求的资源(文件)尽量的多请求,以便客户端向CDN请求后续分块时无需再向源站请求数据。
根据CDN处理Range的方式以及CDN数量、前后顺序提出了两种攻击方式:
该方法的主旨是利用CDN进行Range放大攻击打目标源站,无需一般UDP类反射放大攻击需要源地址伪造。
(论文原图,以访问test.jpg为例)
简单来说就是使用了删除型、扩展型回源策略的CDN,向源站请求尽量大的内容,且响应给客户端的内容依然为Range头预期的小内容。
放大倍数约等于所访问的文件大小/Range请求+响应包大小,论文中统计了test.jpg为1MB的情况,根据不同CDN放大倍数从724倍~1707倍不等(除了KeyCDN为724倍,其余CDN都在1000倍以上)。
(举个例子:上图1+4也就是攻击者与CDN间的交互报文大小为600字节,而请求test.jpg文件大小为1MB,那么此时2+3也就是CDN与源站交互的报文大小约等于1MB,1MB/600B,放大倍数接近1700倍)
理论上,使用删除型策略的CDN的放大倍数可以随着test.jpg大小无限制增大,论文中25MB时最大放大倍数可达4W+倍(Memcached的反射放大攻击最大在5W倍左右)。
而使用扩展型策略的CDN,可能会存在一个Range请求大小的上限,令放大倍数存在一定的限制,不过最次的情况下最大放大倍数也接近了万倍。
此时配合一些手法,令每次对test.jpg访问都不命中缓存并回源进行数据读取,从而造成稳定的放大攻击,持续消耗源站的带宽资源。
论文中的攻击测试结果:目标资源10MB,客户端消耗带宽小于500Kbps,可使目前源站1000Mbps的带宽接近占满。
我自己的测试:通过国外某CDN打我的阿里云ECS主机(上限带宽100Mbps),目标资源文件10MB(实际上用不到这么大的资源文件),20线程直接打满
iftop信息,消耗了大量的流量,以及打满的带宽:
题外话:这种攻击方式配合目前家用的千兆宽带,多线程多CDN节点多个代理进行Range请求,轻轻松松的放大到上T流量,理论上。。。理论上。。。
该方法的主旨是利用Range放大攻击,消耗CDN内部的网络资源。
(继续论文原图)
该方法使用多重范围的Range头,堆叠Range范围数量(bytes=0-,0-,...,0-)(n个0-,CDN支持的n的数量越大放大倍数越大,CDN间消耗的流量等于n倍的访问文件大小),适用于前置CDN(FCDN)采取懒惰型策略,并且后置CDN(BCDN)不检查Range范围是否重叠,就返回分块的Range响应;的CDN组合情况。
同时在客户端处,设置较小的TCP接收窗口,并及时断开连接,使得接收的数据尽量小。
该方法可获得源站文件大小50-6500的流量放大,大量消耗FCDN、BCDN的网络资源。
论文中给了6个CDN结合,一共11种组合的可利用情况,相对SRB来说利用难度较大,一般很少有使用多层CDN的情况。
该方法无法直接威胁到源站。
论文中最后给出了针对不同角色的解决方案,并且已经向已测试的10余家CDN厂商进行了问题通报:
服务器侧:1. 增强本地DDOS防御能力 2.如果接入了CDN,判断是否存在上述问题。
CDN侧:修改Range请求的回源策略,从删除型的扩展型,并且扩展较小的范围(比如在原范围基础上扩展8KB,这样不会浪费太多资源)。
协议侧:修改相关RFC标准,将RangeAMP纳入到考虑范围中。
我们还发现:在静态资源后面加参数,使CDN的缓存MISS是一种常见的Cache MISS手法。(在这种情况下,访问/test.jpg
和访问/test.jpg?xx
,会被当做访问了不同的静态资源文件)
所以,如果确认不需要参数,可直接在CDN上开启忽略参数进行缓存,避免静态资源重复回源,造成SRB方法的放大攻击。
SRB、ORB攻击方法利用了CDN的缓存策略、Range请求进行了放大攻击。
利用本应该用于抗D的CDN来对源站进行流量攻击,以及无意义的消耗CDN网络内部的资源,保护者变成了破坏者。
目前国内很多CDN厂商仍然存在该问题。
https://netsec.ccert.edu.cn/files/papers/cdn-backfire-dsn2020.pdf
https://baike.baidu.com/item/CDN/420951
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Range_requests
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Accept-Ranges
https://www.jianshu.com/p/baf12d367fe7
本文作者:早睡的程序猿
本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/136049.html