反射型XSS:高级利用指南
跨站脚本漏洞无疑是将在未来很长时间内持续困扰应用程序的漏洞类型之一。这种看似简单的注入漏洞通常可被进一步升级,允许攻击者以受害者身份执行恶意操作,甚至更糟的是,以易受攻击的服务器端组件身份执行操作,从读取和更改账户信息(如密码或电子邮件)到访问内部资源和读取本地文件。
在本文中,我们将探讨一种经过验证的方法来识别反射型XSS漏洞,同时深入探讨一些高级利用方法。
什么是跨站脚本(XSS)
跨站脚本(XSS)是一种注入漏洞,允许攻击者将恶意脚本注入到其他用户查看的网页中。它通过利用不足的输入验证和对此用户输入的任何反射缺乏编码来工作,使攻击者能够插入在受害者访问受感染页面时在其浏览器中运行的HTML或JavaScript代码。
根据易受攻击的组件,XSS可以发生在客户端和服务器端。客户端XSS仅发生在受害者的Web浏览器中,它允许攻击者接管受害者的会话。
服务器端XSS(或称为盲XSS)发生在易受攻击的组件使用您未经过清理的输入并在服务器端通过DOM评估它时,例如通过无头Web浏览器。这使攻击者能够使用任意JavaScript代码以服务器身份发起传出请求,在严重情况下甚至读取本地文件(取决于无头Web浏览器的部署配置)。
现在让我们看一下不同类型的XSS漏洞。
反射型XSS
反射型XSS(有时称为反射XSS)发生在恶意用户输入通过请求属性(如URL路径、片段、查询/主体参数或HTTP标头)注入并立即反射回用户而未经适当清理时。
服务器处理用户输入并将其包含在HTTP响应中而没有任何编码,导致受害者的浏览器在点击特制链接时执行攻击者的脚本。
存储型XSS
存储型XSS(有时称为持久XSS)发生在攻击者的恶意脚本保存在目标的数据库、文件系统或任何其他类型的存储服务(如AWS S3)中时。当其他用户稍后检索此存储数据(例如,查看评论部分、公共个人资料或论坛帖子)时,恶意脚本会在其浏览器中执行。
存储型XSS特别危险,因为它可以影响多个受害者,而不需要他们点击特定链接,这与反射型XSS不同。
基于DOM的XSS
基于DOM的XSS发生在不安全的JavaScript代码处理用户可控数据(来自DOM源)并将其传递给DOM接收器时。这允许攻击者制作将由易受攻击的应用程序评估的JavaScript有效负载。
基于DOM的XSS更难发现,因为恶意用户输入不会立即反射到HTTP响应中,而是传递给DOM接收器。基于DOM的XSS漏洞的识别和利用将在后续文章中讨论。
在本文中,我们将仅涵盖反射型和存储型XSS,因为这两种类型具有相同的特征。
什么是自XSS?
自XSS发生在攻击者诱骗受害者在其自己的浏览器中执行恶意JavaScript时,通常通过说服他们将代码粘贴到浏览器的开发者控制台或仅他们可访问的合法网站上的文本字段中(例如,您个人资料上的地址字段)。
虽然这在技术上会导致脚本执行,但大多数漏洞赏金计划和安全研究人员认为自XSS不构成安全风险,因为它需要受害者主动对自己执行攻击,这违反了基本安全原则,即漏洞应该可以在没有广泛社会工程的情况下被利用。
请注意,在某些情况下,自XSS漏洞可以被链接并进一步升级,但这是我们将在后续文章中更广泛涵盖的主题。
方法论
如果您是初学者,这部分至关重要。它可以帮助您节省数小时的时间来确定您是否找到了XSS漏洞或正在处理简单的内容注入。让我们通过这个3步方法来帮助我们识别反射型或存储型XSS漏洞。
步骤1:反射
第一步是识别您的输入在应用程序响应中的反射位置。将唯一字符串(如intigriti1337test)插入各种输入字段、URL参数、标头或任何其他用户可控数据点中。
接下来,在HTTP响应中搜索此字符串。这有助于您映射所有反射点并了解您的输入最终出现在哪里,这对于确定利用是否可能以及您正在处理哪种类型的注入至关重要。
步骤2:注入
找到反射点后,测试是否可以通过注入简单的HTML标签(如<s>intigriti1337test)来跳出当前上下文,并观察应用程序如何处理它。
对于JavaScript上下文中的反射(<script>标签内的任何位置),注入字符串将略有不同。我们将在不久后更深入地讨论这种情况。
输入反射但无注入
您的输入可能已进行HTML编码。在这种情况下,XSS通常不可能,因为您的任意输入已被清理。但是,请记住,存在一些注意事项,应用程序可以根据您的用户代理(移动设备与桌面设备)或当您注入特殊字符(如空字节、CR/LF字符等)时显示不同的行为。
输入反射并注入
当您的输入被反射并注入时,意味着没有特殊字符被编码,您有强烈的迹象表明XSS是可能的。我们现在要做的就是注入特殊的HTML标签或事件处理程序,将我们简单的HTML注入转换为XSS漏洞。
步骤3:有效负载(概念证明)
现在是时候制作一个在受害者浏览器中执行JavaScript的工作概念证明了。为此,您的有效负载取决于两个因素:1)您的输入被反射的上下文,以及2)任何阻止您注入恶意XSS有效负载的现有过滤器。
让我们看一下您的未清理输入可能出现的几种上下文,并浏览一些可以帮助我们跳出它并实现代码执行的有效负载。
通用(HTML上下文)
当您的输入直接反射在HTML正文中而没有被包装在任何特定标签或属性中时,您具有最大的利用灵活性。从简单的有效负载开始,如:
|
|
或:
|
|
上述两个有效负载都将在不需要跳出任何标签的情况下工作。对于初学者来说,这是最简单的情况,因为您可以使用几乎任何支持JavaScript执行的HTML标签,包括<svg>、<iframe>、<object>或自闭合标签上的事件处理程序属性。
HTML属性(内联HTML)
当您的反射出现在HTML属性内部时(如<input value="REFLECTION">或<form action="/path/to/submit?param1=REFLECTION">),您需要首先跳出属性上下文,然后注入您的有效负载。
您可以使用引号关闭属性,使用>关闭整个标签,然后注入新的恶意标签,如"><script>alert(1)</script>,或者通过添加事件处理程序(如" onload=alert(1) x=")停留在同一标签内。
关键是了解用于包装属性的引号类型(单引号或双引号)以及应用程序是否过滤了任何其他可能阻止我们逃离上下文的字符。
JavaScript块
当您的输入在<script>标签内部反射时,通常作为JavaScript变量赋值的一部分,如var data = "REFLECTION";或var config = {"key": "REFLECTION"};,您需要跳出JavaScript语法以执行您的代码。
对于常规字符串,使用"; alert(document.domain); //转义以关闭字符串,执行您的代码,并注释掉其余部分。
对于模板文字(反引号),您可以使用${alert(document.domain)}直接在模板内执行代码而不会破坏语法。
这里的棘手部分是确保在您的注入后JavaScript在语法上仍然有效,因此请注意未闭合的括号、引号或可能引起错误并阻止执行的括号。
XSS利用
我们已经介绍了XSS漏洞是什么以及我们如何系统地探测和识别可能的注入点。现在是时候将我们新获得的技能付诸实践了。让我们看几个真实世界的例子,以更好地帮助我们制作我们的有效负载。
无过滤的XSS
在极少数情况下,您会遇到没有进行任何过滤或验证来防止XSS漏洞的情况。这些通常是由于开发人员忘记清理用户输入而引入的疏忽。
在这些情况下,我们可以使用任何我们喜欢的有效负载来证明XSS的存在:
示例1:无输入清理的基本跨站脚本(XSS)
内联HTML中的XSS(属性)
另一个简单的情况是您的输入反映在HTML属性的值中。在这种情况下,您可以:
- 跳出HTML属性并注入事件处理程序以执行任意JS代码
- 或者,跳出HTML属性,关闭标签,然后打开新标签以执行任意JS代码
根据上下文,注入新的事件处理程序通常要容易得多。而在其他情况下,这可能是唯一可能的解决方案,因为用于打开和关闭HTML标签的字符被明确过滤。
示例2:带有内联HTML有效负载的基本跨站脚本(XSS)
JavaScript上下文中的XSS
随着应用程序变得越来越复杂,开发人员倾向于引入更多的安全弱点,包括XSS漏洞。虽然这种上下文出现得少得多,但有时开发人员将未清理的用户输入直接反射到JavaScript上下文中。通常没有意识到后果,我们可以利用这个机会逃离上下文并注入我们的任意JavaScript代码,而不使用任何HTML。
根据反射点,您通常需要:
- 跳出当前上下文(通常是变量值或函数参数)
- 注入您的有效负载
- 关闭您的有效负载以使语法匹配
示例3:JavaScript代码块内的基本跨站脚本(XSS)
textarea字段内的XSS
浏览器对于某些HTML标签(如<textarea> HTML标签)将拒绝呈现其值以保留内容。如果您是初学者,您可能首先认为这种情况无法利用。但是,如果您的输入曾经反射到任何这些标签内,我们将被迫关闭标签,然后注入我们的有效负载。
示例4:Textarea上下文中的基本跨站脚本(XSS)
允许有限HTML和属性的XSS
您将遇到的一个常见情况是输入受到限制、过滤或在匹配特定模式时被完全阻止。这是开发人员倾向于依赖的最常用的过滤方法之一。
幸运的是,在大多数情况下,我们可以简单地模糊测试任何允许的HTML标签、事件处理程序和字符,以帮助我们规避过滤器或Web应用程序防火墙(WAF)阻止。
示例5:具有有限HTML标签和属性的基本跨站脚本(XSS)
XSS模糊测试
您是否尝试了所有防御措施来使目标执行您的XSS有效负载,但无法规避过滤器?别担心,这是进行XSS模糊测试的强烈迹象!
PortSwigger Research Academy提供了一个包含所有可用HTML标签和属性的备忘单。我们可以使用此列表通过探测我们的注入点来实际枚举所有接受的标签和事件处理程序。之后,我们所要做的就是匹配我们的拼图,通过注入允许的HTML标签和属性来帮助我们制作我们的有效负载!
结论
本文的关键要点是识别您的注入点的上下文并理解您的目标对恶意字符的行为方式。在测试部署严格过滤规则的目标时,建议花时间手动测试您的反射点。一些工具可能很容易无法发现这些,因此不能总是依赖它们。
所以,您刚刚学到了一些关于寻找反射型XSS漏洞的新知识…现在是时候将您的技能付诸实践了!您可以从在易受攻击的实验室和CTF上练习开始,或者…浏览我们在Intigriti上的70多个公共漏洞赏金计划,谁知道呢,也许在您的下一次提交中赚取赏金!