HTTP协议攻击方法汇总(下)

 

最近一段时间,部门的小伙伴们看了一些HTTP协议相关的攻击方法,现做一个汇总。

由于内容比较多,分上下两部分进行发布。

上半部分:https://www.anquanke.com/post/id/224321
下半部分内容:
《Web Cache Attack》作者:donky16
《RangeAMP放大攻击》 作者: fnmsd

 

Web Cache Attack

Web缓存欺骗和Web缓存投毒攻击方式
作者:donky16@360云安全

关于缓存

由于现在网站应用的复杂性,通常一个首页就会进行大量资源的加载,为了使用户更快的加载网页,几乎都会使用缓存,即将一些常用的静态文件,存储起来,当之后再需要这些静态资源的时候,直接就可以拿出来使用。浏览器缓存就是将缓存文件存储在本地,从而减少重复的请求,服务端缓存就是将缓存文件存储在客户端与服务端之间的CDN或者一些代理服务器中。

目前针对Web缓存的攻击方式有很多,以CDN为例,通俗来说,如果CDN会将一些攻击者构造的有害数据或者这些有害数据造成的Web应用异常的响应缓存起来,然后其他用户可以获取,那么将造成用户被攻击,即缓存投毒,如果CDN会将用户的敏感信息缓存起来,然后攻击者可以获取,那么将造成用户数据泄露,即Web缓存欺骗。

Web缓存欺骗

  1. 环境搭建

    以CDN为例,为了更好的搞清楚这种攻击方式的原理,简单地使用Apache2+php搭建了一个网站应用,功能十分简单,index.php可以输入用户名用于登录

info.php可以获取用户名并展示

​ 接着将网站接入了CloudFlare CDN。而最终目的就是攻击者获取正常用户的用户名,真实环境中可以获取更多敏感信息。

  1. 攻击方法
    • 用户正常访问网站并登录获取info.php
    • 攻击者构造http://donky.cn/test/info.php/cache-attack.css链接并诱导用户访问
    • 用户访问http://donky.cn/test/info.php/cache-attack.css,请求到达CDN,CDN第一次接收到此请求,直接转发到源站
    • 源站返回带有usernmaeinfo.php的内容
    • CDN获取到info.php的内容并转发给用户,此时CDN缓存机制发现此请求路径文件拓展名为css,缓存此文件
    • 攻击者访问http://donky.cn/test/info.php/cache-attack.css,CDN发现此请求可以命中缓存,返回info.php内容给攻击者
    • 攻击者获取用户的info.php内容
  1. 攻击分析

    上述是一个理想的攻击链,但是实际情况并不如此

    当访问用户http://donky.cn/test/info.php/cache-attack.css

由于环境是一个简单的php程序,并没有使用任何框架,没有进行相关路由配置,php忽略了url中info.php后面的cache-attack.css直接返回了info.php的内容,这是攻击成功的第一个条件。

接着我们用攻击者的角度去访问这个url

发现并没有获取到用户的username

从响应可以看到,CF-Cache-Status: BYPASS;Cache-Control: no-store, no-cache, must-revalidateCF-Cache-Status是CloudFlare对与此请求缓存的状态记录,可以在CloudFlare-Doc查询

对于源站来说,很明显http://donky.cn/test/info.php/cache-attack.css这个请求返回的并不是静态资源是不允许缓存的,所以在返回包内设置了Cache-Control: no-store, no-cache, must-revalidate,当CloudFlare获取到这种no-store时,自然不会进行缓存

所以要想Web缓存欺骗攻击成功,必须保证缓存服务器会把info.php/cache-attack.css的内容当作css静态资源来进行缓存,这是攻击成功最重要的条件,想到达到这条件有两种方法,源站返回可以进行缓存的Cache-Control或者缓存服务器忽略源站返回的Cache-Control从而进行缓存。

显然第一种方式很难出现,但是对于第二种方式却在很多情况下都可以进行配置,由于网站的复杂性,很多缓存服务器可以自定义缓存策略,以测试的CloudFlare为例,可以通过Page Rule来进行配置,下图可以通过正则的方式实现在test目录下的所有css文件都可以进行缓存

因为http://donky.cn/test/info.php/cache-attack.css正好匹配中http://donky.cn/test/*.css,所以CloudFlare会直接将info.php的内容缓存起来

再次测试上述攻击利用链,当用户访问http://donky.cn/test/info.php/cache-attack.css时,响应包中出现Cache-Control: max-age=14400, must-revalidate; CF-Cache-Status: MISS,此时源站返回的Cache-Control已经被CloudFlare忽略,并设置了缓存信息,由于第一次请求这个url,所以在缓存中是MISS状态,当攻击者再次访问时,会返回缓存的info.php内容,响应包中含有Cache-Control: max-age=14400, must-revalidate; CF-Cache-Status: HIT; Age: 281,命中缓存,达到攻击效果。

Web缓存欺骗总结

  1. 攻击条件
    • 源站应用能够忽略url中正常请求路径后面的静态文件名
    • 缓存服务器能够忽略源站返回的Cache-Control,并把请求获取的内容当作静态文件一样缓存
  2. 对应防御措施
    • 源站对于http://donky.cn/test/info.php/cache-attack.css这种请求,应该做相应的正确处理,而不是仅仅忽略后面的静态文件名
    • 缓存服务器对于源站返回的含有不能进行缓存指令的HTTP头的数据不进行缓存

Web缓存投毒

  1. 缓存键

    由于缓存服务器会缓存一些请求返回的内容,然后当再次接收到相同的请求时,便可以直接取出缓存中的内容返回给客户端。但是如何辨别一个请求是否和缓存中的请求等效,是一件复杂的事情。http头部字段冗杂,通过设置某些字段为缓存键,当缓存键相同时,就认为可以从缓存中取文件资源。

  2. 攻击场景

    请求中一些非缓存键,会影响Web应用返回的响应内容(如把值拼接到返回内容中),并且如果这种请求获取的响应可以被缓存,那么之后的正常用户就会受到攻击。

    unity3d.com就出现过这种问题

    GET / HTTP/1.1
    Host: unity3d.com
    X-Host: portswigger-labs.net

    HTTP/1.1 200 OK
    Via: 1.1 varnish-v4
    Age: 174
    Cache-Control: public, max-age=1800

    \<script src=”https://portswigger-labs.net/sites/files/foo.js”>\</script>

    Web应用把X-Host的值拼接到了返回内容的script标签中,这样可以直接造成XSS,Age: 174Cache-Control: public, max-age=1800可以确认这个请求的响应是会进行缓存的,下一次更新缓存的时间可以通过Agemax-age来确定,这样就能将自己的XSS payload精准地注入到缓存中,达到攻击其他用户的效果。在很多场景下,当我们获取到非缓存键影响的响应内容时,应该搞清楚输入的非缓存键到底影响了什么内容,我们能控制哪些内容,这样才能为之后的攻击创造条件。

引用

https://www.4hou.com/posts/MQkO

https://support.cloudflare.com/hc/en-us/articles/200172516-Understanding-Cloudflare-s-CDN

https://support.cloudflare.com/hc/zh-cn/articles/115003206852

https://www.anquanke.com/post/id/156356

 

RangeAMP放大攻击

作者:fnmsd@360云安全

最近拜读了《CDN Backfired: Amplification Attacks Based on HTTP Range Requests》这篇由清华大学主导的DSN2020最佳论文,做一个简单的笔记。

论文下载地址:

https://netsec.ccert.edu.cn/files/papers/cdn-backfire-dsn2020.pdf

此处先膜一下各位论文作者,tql~

基本概念

首先是两个概念,了解的可以直接跳过:

CDN(这里主要指的是HTTP协议的CDN):

CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。

目前主要形式还是以反向代理,产品有很多CloudFlare、AWS的CloudFront;阿里云、腾讯云的CDN产品;云WAF也基本上都带有CDN功能。

单独说一下CDN缓存:

当服务接入了 CDN 之后,浏览器本地缓存的资源过期之后,浏览器不是直接向源服务器请求资源,而是转而向 CDN 边缘节点请求资源。CDN 边缘节点中将用户的数据缓存起来,如果 CDN 中的缓存也过期了,CDN 边缘节点会向源服务器发出回源请求,从而来获取最新资源。

一些CDN的缓存可以通过加请求参数、更改请求头等等方法,令已缓存的资源资源被认为未缓存,进而令CDN回源站进行读取。

HTTP Range请求(HTTP范围请求):

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数量、前后顺序提出了两种攻击方式:

Small Byte Range(SBR)Attack(小字节范围攻击)

该方法的主旨是利用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流量,理论上。。。理论上。。。

Overlapping Byte Ranges(ORB) Attack(重叠字节范围攻击)

该方法的主旨是利用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的情况。

该方法无法直接威胁到源站。

 

解决方案

论文中最后给出了针对不同角色的解决方案:

服务器侧:1. 增强本地DDOS防御能力 2.如果接入了CDN,判断是否存在上述问题。

CDN侧:修改Range请求的回源策略,从删除型的扩展型,并且扩展较小的范围(比如在原范围基础上扩展8KB,这样不会浪费太多资源)。

协议侧:修改相关RFC标准,将RangeAMP纳入到考虑范围中。

我们还发现:在静态资源后面加参数,使CDN的缓存MISS是一种常见的Cache MISS手法。(在这种情况下,访问/test.jpg和访问/test.jpg?xx,会被当做访问了不同的静态资源文件)

所以,如果确认不需要参数,可直接在CDN上开启忽略参数进行缓存,避免静态资源重复回源,造成RangeAMP放大攻击。

 

总结

SRB、ORB攻击方法利用了CDN的缓存策略、Range请求进行了放大攻击。

利用本应该用于抗D的CDN来对源站进行流量攻击,以及无意义的消耗CDN网络内部的资源,保护者变成了破坏者。

 

引用内容

  1. https://netsec.ccert.edu.cn/files/papers/cdn-backfire-dsn2020.pdf
  2. https://baike.baidu.com/item/CDN/420951
  3. https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Range_requests
  4. https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Accept-Ranges
  5. https://www.jianshu.com/p/baf12d367fe7
(完)