-
在测试 XSS 时,重要的是要考虑所有类型的利用,并注意所有看起来有趣的东西。
-
即使某些东西现在可能无法利用,也要尝试看看它在链式利用中的潜力。
-
很多时候,漏洞利用链是由无法利用的链接组成的,这些链接本身是无用的,但当链接在一起时可能是致命的。
-
在 Glassdoor 中,我在/Job/new-york-ny-compliance-officer-jobs-SRCH_IL.0,11_IC1132348_KO12,42069.htm
-
我发现参数名称(和值也是)反映在未处理的响应中
-
看到这个我很惊讶,因为这应该很早就被发现了。Glassdoor 程序有近 800 份提交,所以我没有错误地认为我是唯一注意到它的人
-
该参数反映在脚本标签中的字符串中,因此要实现 XSS,我有 2 个选项
-
转义字符串并注入 javascript
-
关闭脚本标签并注入通用 XSS 有效负载
-
对于第一个选项,字符串似乎已经用反斜杠转义了,不幸的是绕过这个很难。
-
但是,我的第二个选项具有更大的潜力,因为没有对用户输入进行清理,因此注入结束脚本标签应该可以解决问题
-
然而,在我输入的那一刻?</script>(为了便于阅读,此处为 URL 解码)我的请求立即被 WAF 关闭并阻止。这是非常期待的,但是我早餐吃WAF>:)
-
在尝试与 WAF 对抗之前,我们必须了解游戏规则。
-
我看到人们在尝试绕过 WAF 时犯的一个常见错误,或者只是一般的过滤器,是他们复制和粘贴通用 WAF 绕过有效负载,而没有真正理解WAF 阻止他们的请求的*原因。*根据我的经验,喷涂和祈祷WAF通常是浪费时间,因此最好手动测试它们,最重要的是了解它们
-
所以我绕过 WAF 的第一步是从一个被阻止的有效负载开始,然后逐个字符地删除,直到 WAF 让我通过
-
幸运的是,我们很快就与 WAF 达成协议。我所要做的就是删除大于>号,我得到了 200。
-
所以现在的问题是它还有什么不喜欢的?似乎之后的任何角色</script都会引起 WAF 的注意,</scriptaaa例如
-
如果 WAF 真的阻塞了,这将是一个大问题</script*,但幸运的是,WAF 确实允许空格字符,例如%20(space),这意味着最终,脚本标签将在下一个即将到来的大于>号时关闭
-
所以现在,下一步转向寻找一个新的未经处理的注入点,这将允许我们关闭脚本并注入一个 HTML XSS 有效负载
-
我试图查看是否可以将有效负载分解成带有其他参数的部分,但是它也被阻止了。似乎 WAF 规则应用于整个 URL,而不是单个参数。幸运的是,我之前绕过了这些类型的 WAF
-
我的第一个 goto 技术是基于字母数字的 HTTP 参数污染,我过去已经使用它来绕过这个程序中的类似 WAF。
-
字母数字参数污染滥用了反射查询的字母数字顺序,因此可以通过将有效负载向后分解为不同的参数来绕过这样的 WAF
-
不幸的是,这里的情况似乎并非如此,但我将发布一篇关于我如何使用这种技术来实现反射型 XSS 的文章
-
此时我对这个端点失去了一点希望,所以我决定寻找链环漏洞而不是独立漏洞。这是我开始看饼干的时候
-
这时我注意到在注入点旁边,实际上有一个值来自optimizelyEndUserId我请求中的 cookie。
-
我需要做的就是关闭脚本标签并注入 HTML。注入><svg>cookie 似乎可以解决问题。
-
现在我需要实际执行javascript。我们已经克服了困难的部分,所以现在当我们能够通过 WAF 偷运一个 svg 标签时,剩下的应该很容易
-
一个非常通用的 WAF 绕过有效负载似乎可以解决问题:><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
-
然而,它是一个自我 XSS,只有在我们能够控制 cookie 时才存在
-
然而,这可能会升级为带有缓存中毒的反射 XSS,所以这就是我接下来开始寻找的东西(我知道我在描述中说过存储 XSS,我保证我们会很快到达那里!)
-
Web Cache Poisoning 可用于许多事情。首先想到的是 1) 存储型 XSS 2) 将不可利用的 XSS 升级为反射型 XSS 3) DoS
-
在我发现缓存规则的时候,我已经意识到了无法利用的 XSS 中/Job/new-york-ny-compliance-officer-jobs-SRCH_IL.0,11_IC1132348_KO12,42069.htm?VULN%3C/script%20,因此尝试将这两个错误链接到反射 XSS 漏洞中感觉就像是自然而然的事情
-
我回到工作路径做更多的研究。我想看看是否还有其他易受自身 XSS 攻击的端点,并且确实存在。
-
我发现Job路径下的每个页面都容易受到self XSS的攻击,太棒了!我更进一步,注意到即使是应该是 404 的页面,实际上也返回了 200,并且太容易受到自身 XSS 的攻击。
-
因此,回顾一下重要信息:
-
CDN 有一个规则会缓存/Award/*
-
上有一个自我 XSS 漏洞/Job/*
-
这两个漏洞的攻击面不是"静态的",而是依赖于一个非常宽松的通配符模式,这让我想到:"这些模式真的 能接受任何东西吗?服务器会将模式优先于特殊的 URL 语法(例如点段/../),还是将 URL 规范化然后匹配模式?"
-
或者换句话说:"后端服务器和前端服务器的 URL 解析器都会规范化点段吗?"
-
为了测试这一点,我在假设 URL 解析器标准化点段的情况下尝试了这两个有效负载:
-
/Award/../this_should_not_cache
-
/Job/../this_should_give_a_404
-
令我惊讶的是,它们产生了相互矛盾的结果
-
奖励负载没有被缓存,这意味着前端服务器的 URL 解析器在匹配缓存规则之前会规范化点段
-
但是,作业路径返回 200,这意味着 Web 服务器没有规范化点段。
-
所以总结这个简短的测试,我们可以说前端服务器和后端服务器在如何解析点段方面存在分歧
-
知道了这一点,我们可以构造以下有效载荷:
GET /Job/../Award/RANDOMPATHTATDOESNOTEXIST?cachebuster=046&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
-
由于网络服务器不会对点段进行规范化,因此我们将通过 XSS 获得响应
-
但是,由于前端将规范化点段,它将被缓存(并存储)在/Award/RANDOMPATHTATDOESNOTEXIST?cachebuster=046&attack=VULN%3C/script%20
-
所以现在,当受害者访问时https://glassdoor.com/Award/RANDOMPATHTATDOESNOTEXIST?cachebuster=046&attack=VULN%3C/script%20,他们会从 CDN 中获取带有 XSS 的存储响应
-
因此,一旦我能够获得反射 XSS 的有效 PoC,我立即报告。
-
但是,我仍然不够满意,因为我知道存储型 XSS 在适当的条件下应该是可能的
-
所以我一直在寻找一个真正所有基于标题的 XSS,并且行为类似于/Job/*,在它下面的每个页面下都可能存在 XSS。
-
那是我记得我第一次向 glassdoor 报告的时候,它是 http://glassdoor.com/mz-survey/start_input.htm 中通过字母数字有序参数污染反映的 XSS(当时它仍在分流中,所以它不是固定的)。
-
我想也许我也能在那里找到一个标头 XSS,所以我一直在寻找
-
对我来说幸运的是,报告中反映的 XSS 也容易受到完整标头 XSS 的攻击!但它的行为不像/Job/*它下面的每个页面都容易受到攻击,所以它几乎没用
-
我确实记得不仅有一个端点易受攻击,还有很多其他端点
-
幸运的是,我最终能够找到一个端点,它既容易受到标头 XSS 的攻击,又表现得像/Job/*在测试了我之前报告的每个易受攻击的端点并得到了这个:https://glassdoor.com/mz-survey/interview/收集问题_输入.htm/
-
有效载荷看起来像这样
GET /mz-survey/interview/collectQuestions_input.htm/../../../Award/RANDOMPATHTATDOESNOTEXIST123?cachebuster=050 HTTP/2
Host: www.glassdoor.com
X-Forwarded-For: VULN
X-Forwarded-For: VULN><svg/onload=selfalert>
Cookie: gdId=VULN%22</script%20
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
-
将 XSS 有效负载拆分为 2 个标头和一个 cookie 的原因是绕过 WAF,因为我无法将整个有效负载放入一个 cookie 或标头
-
X-Forwarded-For 标头反映在 cookie 之后,因此我继续有效载荷的机会就在那里。
-
不幸的是,WAF 对 X-Forwarded-For 标头更加严格,因为我无法使用任何特殊字符
-
有趣的是,还有另一个很酷的标头混淆,WAF 只阻止了第一个 X-Forwarded-For 标头,但网络服务器解释并反映了两者。这让我可以轻松绕过 WAF,方法是为第一个 X-Forwarded-For 标头提供有效值,但在第二个 X-Forwarded-For 标头中提供我的 XSS 有效负载的其余部分。这可以在上面的有效载荷中看到