url重定向漏洞危害_BlackHat2020议题之Web缓存投毒_小白攻防指南

url重定向漏洞危害_BlackHat2020议题之Web缓存投毒_小白攻防指南

url重定向漏洞_url重定向漏洞危害_url重定向攻击漏洞

它的cache key就可以为https|GET|.net|/?x=1,注意我这里的用词,是“可以为”,也就是说cache key的生成规则不是固定的,不同的网站、应用的cache key生成规则是不一样的,这个是可以自定义的

http请求中没有被用作cache key的部分我们称其为“”元素,如果一个的元素可以被用来生成一个危险的响应,那么我们就可以利用这个元素来进行缓存投毒,并影响其它用户。

文字阐述可能不是太好理解,那么我举一个?,现在有如下场景

url重定向漏洞危害_url重定向漏洞_url重定向攻击漏洞

可以看到,响应中将请求头X--Host的值直接拼接到meta标签的属性中了,这是很明显的一处反射型xss

由于输入点是在请求头中,所以利用难度稍微有一点点大

但是,只要我们配合上缓存投毒,这个漏洞一下子变得??起来,由于X--Host这个头不是cache key的一部分,所以,以下两个请求被认为是一致的

代码语言:

复制

GET /en?dontpoisoneveryone=1 HTTP/1.1
Host: www.redhat.com
X-Forwarded-Host: a.">

vs

代码语言:

复制

GET /en?cb=1 HTTP/1.1
Host: www.redhat.com

如果我们先发送第一个请求到服务器,服务器就会返回如下响应,并缓存到缓存服务器中

代码语言:

复制

HTTP/1.1 200 OK
Cache-Control: public, no-cache
…
"/> 

很明显,这是一个存在xss的恶意响应

当其他用户下一次正常访问/en?cb=1页面时,会发送上述第二个请求,由于两个请求的cache key一致,服务器认为他们请求的同一个资源,所以就会把之前我们投毒的恶意缓存返回给用户,从而造成用户被xss

投毒流程大体如下

url重定向漏洞_url重定向攻击漏洞_url重定向漏洞危害

之前的一些研究

其实在2018年James 就已经针对Web缓存投毒进行过研究了,并发布了一篇paper

这篇paper中主要研究的是利用非标准的http请求头来给缓存投毒,例如X--Host和 X--URL,当然,这也是比较简单直接的一种投毒方法

但是,本文的内容则不太一样了,本文的研究对象是那些以往经常出现在cache key中的元素,例如host头、path或者query。

当然,如果这些元素是直接放到cache key中作为cache key的一部分的话是不可能被投毒的

但是,我们发现这些元素在放入cache key之前总会被解析、转换或者规范化,正是这些前置操作导致了我们可以利用它们

那么,要怎么利用呢?我们接着往下看

利用方法

Web缓存投毒从挖掘到利用可以归结为下面这张图片

url重定向攻击漏洞_url重定向漏洞危害_url重定向漏洞

我来大概解释一下这张图:

理解cache的工作机制

首先咱们得找到一处可以利用的缓存页面,那怎样才算是一处可以利用的缓存点呢?需要满足以下几点

只有url或者参数被回显到了响应中我们才可以进行投毒,而且这些回显也可以帮助我们探索cache与web服务器在处理请求上的差异(现在不懂什么意思不要纠结,看完就懂了,接着往下吧)

在最幸运的情况下,服务器会直接告诉我们cache key,这样就省得我们自己探索了,当然,也可能返回给你多个cache key,不要慌张,这些cache key可能适用不同的场景,我们只要找到当前场景下正确的cache key就行

代码语言:

复制

GET /?param=1 HTTP/1.1
Host: example.com
Origin: zxcv
Pragma: akamai-x-get-cache-key, akamai-x-get-true-cache-key
HTTP/1.1 200 OK
X-Cache-Key: /example.com/index.loggedout.html?akamai-transform=9 cid=__Origin=zxcv
X-Cache-Key-Extended-Internal-Use-Only: /example.com/index.loggedout.html?akamai-transform=9 vcd=1234 cid=__Origin=zxcv
X-True-Cache-Key: /example.com/index.loggedout.html vcd=1234 cid=__Origin=zxcv

然后,我们还得进一步搞清楚cache key是根据什么规则形成的,在形成过程中是否有如下情况

例如去掉特定的参数、去掉请求的所有参数、去掉host头中的端口、url解码等等,在进行完这些操作过后,再把他们放入cache key,这种行为是很危险的

那么要怎么搞清楚服务器是否进行了上述的转换呢?其实很简单,只要发送两个稍微不同的请求并观察第二个是否命中缓存就可以知道

为了便于理解,我们来看一个例子,现在有如下请求,该网站会把host头的内容作为头的一部分进行跳转

代码语言:

复制

GET / HTTP/1.1
Host: redacted.com
HTTP/1.1 301 Moved Permanently
Location: https://redacted.com/en
CF-Cache-Status: MISS

例如,我们要探测目标站点在形成cache key的过程中有没有去掉host头中的端口号,那么我们首先发送如下请求

url重定向漏洞危害_url重定向漏洞_url重定向攻击漏洞

然后再发送一个host头中没有端口号的请求,并观察它是否命中缓存

url重定向漏洞_url重定向攻击漏洞_url重定向漏洞危害

如果命中了缓存,这说明网站在生成cache key的过程中的确移除了host头中的port

在这个场景下,我们就可以向缓存投毒,让所有用户都跳转到一个未开放的端口,从而造成Dos攻击

这个漏洞存在于很多CDN厂商上,包括和,我通知了他们,但是拒绝修复...

注:通常情况下,上面的信息我们可以利用泄露、 源码、文档等方式获得

利用

利用就没什么好说的了,就是结合其他漏洞或者利用链,一般有三种利用方法

我知道,后面两种利用场景可能比较难理解,大家也不必急于理解,因为后面会有相应的案例

案例学习

上面说了那么多,可能大家都还处在比较懵的状态,对于某些点不是特别清楚,所以现在咱们来看一些真实的案例,这些案例都是我在各大src中挖到的

Query 探测

在形成cache key的过程中,最常见的转换就是去掉整个query字符串,也就是/axin/.html?true=1这个链接指向的资源,在形成cache key的过程中会去掉?true=1。

这种情况下,是比较难发觉目标站点使用了缓存的,你可能会直接认为他是一个静态站点...

对于动态的站点,我们一般可以通过改变参数值的方式来识别,因为动态站点在我们改变某个参数的时候与之对应的响应也会改变,例如:

代码语言:

复制

GET /?q=axin HTTP/1.1
Host: example.com
HTTP/1.1 200 OK

但是,当站点在形成cache key的过程中移除掉整个query字符串的情况下,我们就不能够再使用这种方式识别动态站点了,因为你再怎么更改参数甚至是添加一个参数都会得到相同的响应,你不由得会开始思考人生?,就像下面这样

代码语言:

复制

GET /?q=canary&cachebuster=1234 HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
CF-Cache-Status: HIT
GET /?q=canary&cachebust=nwf4ws HTTP/1.1
Host: example.com
Accept-Encoding: gzip, deflate, nwf4ws
Accept: */*, text/nwf4ws
Cookie: nwf4ws=1
Origin: https://nwf4ws.example.com

这个方法在某些系统上效果拔群,例如,它默认把这个头当做cache key的一部分。

但是,这个方法在另外一些系统上就不那么ok了,这些系统上没有使用头作为cache key的一部分,且我使用的这个头可能会对系统造成破坏...

幸运的是,我们还有其他办法挽救,在某些系统上,我们可以使用http方法PURGE和来清除缓存,这在真实环境下是个很好的技巧(投毒搞出大问题还可以一键重置,就问你香不香)

除此之外,我们都知道,大多数的系统都会把path作为cache key的一部分,又因为后端系统存在path规范化,这就导致不同的cache key也可以命中同样的资源,例如针对/目录,在不同系统上有不同的命中方法

代码语言:

复制

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

所以,利用这一特性,在真实环境中,为了不影响其他用户,我们可以在确定漏洞存在的同时只对自己投毒

例如,我想//axin/.html页面投毒,可以证明/axin/.html存在漏洞,但是又不影响其他用户,因为正常用户一般不会请求//axin/.html

Query利用

如果你学会了上面的方法,你就会发现更多的漏洞,例如我在一个新闻网站发现的一处反射型xss缓存投毒

url重定向漏洞危害_url重定向攻击漏洞_url重定向漏洞

代码语言:

复制

Cache Key: https://redacted-newspaper.net//

原本像缓存投毒这种漏洞都是很容易就被别人提交了的,但是,由于目标系统去除掉了整个query字符串,这会迷惑大多数白帽子,让他们以为这是一个静态页面。

由于query字符串没有被包含到cache key中,所以,当用户请求如下页面时会返回被我们投毒后的页面,从而触发xss

代码语言:

复制

GET // HTTP/1.1
Host: redacted-newspaper.net
HTTP/1.1 200 OK
...
"/>

代码语言:

复制

Cache Key: https://redacted-newspaper.net//

上面用了两个/是为了在测试时不影响正常用户

重定向Dos

如果一个站点没有很好利用的xss,我们该咋办呢?

由于我个人比较喜欢向缓存服务提供商投毒,所以,我就拿举个例子

的登录页面在dash..com/login,但是很多链接在跳转该页面时都使用的是/login/,注意最后多了一个/,这个斜杠很关键

经过一番探索,我发现目标把query字符串从cache key中去除掉了

代码语言:

复制

GET /login?x=abc HTTP/1.1
Host: www.cloudflare.com
Origin: https://dontpoisoneveryone/
HTTP/1.1 301 Moved Permanently
Location: /login/?x=abc

代码语言:

复制

GET /login HTTP/1.1
Host: www.cloudflare.com
Origin: https://dontpoisoneveryone/
HTTP/1.1 301 Moved Permanently
Location: /login/?x=abc

一眼看上去,好像这里没啥可以利用的点,但是

我们可以用一点小技巧,把这个请求变为一个Dos攻击,方法很简单,只要我们把query字符串变得更长,直接达到url允许的最大长度:

代码语言:

复制

GET /login?x=very-long-string... HTTP/1.1
Host: www.cloudflare.com
Origin: https://dontpoisoneveryone/

这样,当下一个用户访问这个登录页面时,就会被重定向到我们投毒的地址去

代码语言:

复制

GET /login HTTP/1.1
Host: www.cloudflare.com
Origin: https://dontpoisoneveryone/
HTTP/1.1 301 Moved Permanently
Location: /login/?x=very-long-string...

由于我们投毒的query字符串已经达到了url的最大长度,而这次重定向会多一个/,这就导致超出了url允许的最大长度,结果就是服务器不会接受这样一个请求

代码语言:

复制

GET /login/?x=very-long-string... HTTP/1.1
Host: www.cloudflare.com
Origin: https://dontpoisoneveryone/
HTTP/1.1 414 Request-URI Too Large
CF-Cache-Status: MISS

当我把这个问题提交给时,一开始他们只打算在自己的站点上修复这个问题,但是考虑到使用他们产品的用户太多了,所以,他们采用了全局的防御措施——他们禁用了那些直接将query字符串回显到头的缓存

可是,这很容易就被绕过了...

代码语言:

复制

GET /login?x=%6cong-string… HTTP/1.1
Host: www.cloudflare.com
HTTP/1.1 301 Moved Permanently
Location: /login/?x=long-string…
CF-Cache-Status: HIT

虽然这个问题已经被修复,但是如果你发现其他服务器在把一个query字符串放到头中前进行了一些其他的转换操作,你仍然有机会绕过防御

缓存参数隐藏

目前为止,我们看到的都是把整个query字符串从cache key去除会造成漏洞。那么如果一个站点只是把某个特定的参数从cache key中去除掉会带来什么后果呢?

理论上,只要一个站点不把整个url回显到响应中就不会有啥问题。但是,在实操的时候,由于站点采用的各种奇奇怪怪的把特定参数从cache key中去除的方法,导致,我们可以方法来污染缓存,我把这种攻击叫做cache 。

例如有这样一个站点,它采用如下正则把参数_从cache key中移除:

代码语言:

复制

set req.http.hash_url = regsuball(
           req.http.hash_url,
           "\?_=[^&]+&",
           "?");

然后我们有这样一个请求:

代码语言:

复制

GET /search?q=help?!&search=1 HTTP/1.1
Host: example.com

在这种情况下,我们就可以在不改变cache key的情况下污染参数q

代码语言:

复制

GET /search?q=help?_=payload&!&search=1 HTTP/1.1
Host: example.com

由于正则会把字符串替换为一个?,所以,我们只能向带有问号的参数投毒。其他类似这样的场景还有很多,这些替换规则会给漏洞利用带来很多的限制

的一个案例

站点上有这样一个请求

url重定向攻击漏洞_url重定向漏洞_url重定向漏洞危害

不知道你有没有注意到这个请求的响应中返回了cache key?而且这个cache key中居然没有参数-

很明显,的cache key是不包含-参数的,也就是说我们可以向它投毒,而且,由于那脆弱的URL解析规则,我们可以向任何参数投毒,例如向参数x投毒

代码语言:

复制

GET /en?x=1?akamai-transform=payload-goes-here HTTP/1.1
Host: redacted.com
HTTP/1.1 200 OK
X-True-Cache-Key: /L/redacted.akadns.net/en?x=1 vcd=1234 cid=__

Ruby on Rails案例

在测试某一个目标时,我通过扫描器发现了一个奇怪的现象,但是,我又没有找到可利用的缓存点,于是我看了一下目标站点的缓存实现源代码。

而且,后面我发现这个站点是基于Ruby on Rails的,并且Ruby on Rails会把;当做参数分隔符,类似于&,也就是说下面两个链接是等价的

代码语言:

复制

/?param1=test&param2=foo
/?param1=test;param2=foo

这一个把参数排除在 key之外的系统上,对于下面这样一个请求,只会看到一个参数,那就是:

代码语言:

复制

GET /jsonp?callback=legit&utm_content=x;callback=alert(1)// HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
alert(1)//(some-data)

代码语言:

复制

GET /jsonp?callback=legit HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
X-Cache: HIT
alert(1)//(some-data)

但是,Rails却看到的是三个参数:, , and ,由于有两个,所以,后一个参数的值会覆盖前一个

的方法

有一些系统没有把http请求的方法作为cache key的一部分,这时候我们还可以使用post方法来对cache key隐藏参数,当然,这要求那个接口既支持get方法也支持post方法,并且会把参数回显到响应中

代码语言:

复制

POST /view/o2o/shop HTTP/1.1Host: alijk.m..=a000推荐

~

网络安全学习,我们一起交流

~

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值