我将展示我是如何能够通过反射型和存储型XSS在Glassdoor上对数千个页面进行缓存投毒的(漏洞挖掘)。
介绍
想象一下,你的朋友推荐了一个新的、看起来很酷的漏洞赏金项目给你,你听说有人通过这个挑战赚了不少钱,学了不少技能,所以你兴奋地开始尝试。但是,经过几天紧张的探索和研究,你却两手空空、一无所获。你开始怀疑自己,所以你开始寻找低危漏洞,突然你发现了一个header XSS。起初你不以为然,直到你意识到目标系统有个缓存服务器(比如CloudFlare)!你尝试找到一种缓存XSS的方法,但一直失败。你运气很不好,看起来他们这个端点存在web缓存投毒保护,使得XSS无法被缓存。就在你以为你发现了高危漏洞时,现实给了你一记重拳,让你感觉无路可走。那现在你打算怎么办呢?要不要试一试URL解析混淆?
寻找XSS
当测试XSS的时候,你需要考虑到所有类型的利用方法,并且记下所有看起来有趣的内容。就算有些地方现在无法利用,试试看它有没有可能和其他漏洞进行组合。很多时候,攻击链由本身无法利用的链接组成,这些链接单独看来是无用的,但当它们链接在一起时可能会造成致命的后果。在Glassdoor,我发现了上述这种端点:/Job/new-york-ny-compliance-officer-jobs-SRCH_IL.0,11_IC1132348_KO12,42069.htm
。
我发现参数名(以及参数值)在响应中未经过滤地被映射出来。看到这一点我非常惊讶,因为这应该早就被发现了。Glassdoor有将近800个漏洞提交,所以我并不认为只有我注意到这一点。这个参数在脚本标签中的一个字符串里被反射,所以为了实现XSS,我有两种选择:
逃逸字符串并注入JavaScript
关闭脚本标签并注入一个通用的XSS payload
对于第一种选择,字符串似乎已经用反斜杠进行了转义,绕过这种转义很难。第二种选择看起来就有戏多了,因为用户的输入都没有被过滤,所以注入一个</script>
应该能成功。然而,当我放入?</script>
(这里为了便于阅读进行了URL解码)时,我的请求立刻被WAF拦截并阻止了。这完全在我预料之中,不过我对付WAF就像吃早餐一样轻松 >:)。【这个表情有点意思,你头往左歪是个邪恶的笑脸,头往右歪是个sad的表情】
在试着和WAF斗智斗勇之前,我们必须先了解这个WAF的规则。一个我经常看到的错误是,当人们试图绕过WAF或一般的过滤器时,他们会复制和粘贴通用的WAF绕过payload,而实际上并不理解WAF为什么会阻止他们的请求。根据我的经验,疯狂尝试和祈祷绕过WAF能成功通常是浪费时间,所以最好是手动测试它们,理解它们的特定规则。所以我绕WAF的第一步就是对被拦截的payload,一个字符一个字符地移除,直到WAF让它通过。幸运的是,我和WAF很快达成了一致。我只需要移除>
就可以得到200响应。
所以现在的问题是,还是什么字符WAF不喜欢?看起来</script
之后的任何字符都会引起WAF的注意,比如</scriptaaa
。如果WAF真的阻止了</script*
那就难搞了,但幸运的是WAF允许空白字符,例如%20
(空格),这意味着最终脚本标签将在下一个出现的>
处关闭。
所以现在,下一步就变成了找到一个新的未被过滤的注入点,它允许我们关闭script标签并且注入一个HTML XSS payload。我试着是否能用其他参数把payload分成几部分,然而也被WAF阻止了。看来WAF的规则适用整个URL,而不是单独的参数。幸运的是,我之前就已经绕过了这一类的WAF。
我首先采用的技术是基于字母数字的HTTP参数污染,我在过去已经用它绕过了这个程序中的一个类似的WAF。字母数字参数污染(详见下文解释)利用了字母数字参数的排序先后,因此将你的payload逆向分解到不同的参数中,可以绕过这样的WAF。不幸的是,这里和之前的情况不尽相同。
此时我对这个端点失去了一些希望,所以我决定寻找一个漏洞与它组合利用。我开始留意cookie。此时我注意到了在注入点的附近,还真有这样一个值,它来自于我的请求中的optimizelyEndUserId
cookie。
我现在需要做的是关闭脚本标签并注入HTML,在cookie里注入><svg>
似乎能解决这个问题。现在我需要实际执行JavaScript。我们已经度过了困难的部分,所以现在如果我们能够将一个SVG标签绕过WAF时,剩下的应该很容易。
一个牛批的通用WAF绕过payload似乎可以解决这个问题:><svg/onload=a=self['aler'%2B't']%3Ba(document.domain)>·
。现在我们得到了一个这样的XSS:
GET /Job/new-york-ny-compliance-officer-jobs-SRCH_IL.0,11_IC1132348_KO12,42069.htm?attack=VULN%3C/script%20 HTTP/2
Host: www.glassdoor.com
Cookie: optimizelyEndUserId=BRUH><svg/onload=a=self['aler'%2B't']%3Ba(document.domain)>
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Content-Length: 0
然而,这是一个Self XSS(不仅需要用户点击链接就能触发,还需要控制cookies)。但是,这可能会升级为通过缓存投毒的反射型XSS,所以这就是我接下来要开始寻找的。
字母数字参数污染(alphanumeric parameter pollution):
字母数字参数(alphanumeric parameter)是什么?
"Alphanumeric parameter"指的是包含字母和数字的参数。
参数污染(parameter pollution)是什么?
一句话来说就是不同的系统对于同名参数取哪个的问题有着不同的规则,利用这种规则在某些情况下可以篡改参数。
如果还是有些云里雾里可以去看一下这篇文章(很简单很短):https://alonnsoandres.medium.com/http-parameter-pollution-ff14df6b018
寻找有宽松规则的缓存
刚开始搜寻时,我总是喜欢测试缓存以查看它是如何表现的。如果我看到一条路径被缓存了,我总是测试它的极限。许多网站有着自己独特的规则缓存特定的路径和文件,所以手动测试这些规则是熟悉缓存服务器的不二之选。
当我刚开始手动测试这些缓存规则时,我经常会先搞乱扩展名。我会移除、增加或改变扩展名然后仔细观察响应包里的缓存头和内容。当我测试完扩展名之后,我会测试路径本身。
例如,我注意到https://www.glassdoor.com/Award/new-york-ny-com