基于DOM的XSS
在本节中,我们将描述基于DOM的跨站脚本(DOM型XSS),讲解如何发现DOM型XSS漏洞,并讨论如何利用不同的源和接收器来利用DOM型XSS。
什么是基于DOM的跨站脚本?
基于DOM的XSS漏洞通常发生在JavaScript从攻击者可控制的源(如URL)获取数据,并将其传递到支持动态代码执行的接收器(如eval()
或innerHTML
)时。这样,攻击者就可以执行恶意JavaScript,通常能够劫持其他用户的账户。
要实施基于DOM的XSS攻击,你需要将数据放入源中,使其传播到接收器并导致任意JavaScript的执行。
对于DOM型XSS,最常见的源是URL,通常通过window.location
对象访问。攻击者可以通过在URL的查询字符串和片段部分中嵌入有效载荷来构造一个链接,将受害者引导到一个存在漏洞的页面。在某些情况下,比如在针对404页面或运行PHP的网站时,有效载荷也可以放置在路径中。
有关源与接收器之间污染流的详细解释,请参阅基于DOM的漏洞。
如何测试基于DOM的跨站脚本
大多数DOM型XSS漏洞可以通过Burp Suite的Web漏洞扫描器快速可靠地找到。手动测试基于DOM的跨站脚本,通常需要使用带有开发者工具的浏览器,如Chrome。你需要逐个检查每个可用的源,并逐个进行测试。
测试HTML接收器
要测试HTML接收器中的DOM型XSS,可以将一个随机的字母数字字符串放入源(如location.search
),然后使用开发者工具检查HTML并找到字符串出现的位置。请注意,浏览器的查看源代码选项不适用于DOM型XSS测试,因为它未考虑JavaScript对HTML所做的更改。在Chrome的开发者工具中,你可以使用Control+F
(或MacOS上的Command+F
)在DOM中搜索字符串。
对于字符串出现在DOM中的每个位置,都需要确定上下文。基于这个上下文,改进你的输入以查看它是如何被处理的。例如,如果你的字符串出现在一个双引号属性中,那么尝试在字符串中注入双引号,看看是否可以跳出该属性。
请注意,浏览器对URL编码的处理方式各不相同,Chrome、Firefox和Safari会对location.search
和location.hash
进行URL编码,而IE11和Microsoft Edge(Chromium之前的版本)不会对这些源进行URL编码。如果你的数据在处理之前就被URL编码,那么XSS攻击不太可能奏效。
测试JavaScript执行接收器
针对基于DOM的XSS进行JavaScript执行接收器测试要稍微困难一些。对于这些接收器,你的输入不一定会出现在DOM中,因此无法对其进行搜索。相反,你需要使用JavaScript调试器来确定输入是否以及如何被发送到接收器。
对于每个潜在的源,如location
,首先需要在页面的JavaScript代码中找到源被引用的地方。在Chrome的开发者工具中,你可以使用Control+Shift+F
(或MacOS上的Command+Alt+F
)搜索页面上的所有JavaScript代码以找到源。
一旦找到源被读取的地方,就可以使用JavaScript调试器添加一个断点,并跟踪源的值如何被使用。可能你会发现源被分配给了其他变量。如果是这种情况,就需要再次使用搜索功能来跟踪这些变量,看看它们是否被传递给了接收器。当找到一个接收来自源的数据的接收器时,你可以使用调试器检查变量的值,方法是将鼠标悬停在变量上,显示其被发送到接收器之前的值。然后,与HTML接收器一样,改进你的输入,看看是否可以成功实施XSS攻击。
使用DOM Invader测试DOM型XSS
在实际环境中识别和利用DOM型XSS可能是一个繁琐的过程,通常需要手动遍历复杂的、经过精简的JavaScript。不过,如果使用Burp的浏览器,就可以利用其内置的DOM Invader扩展,它能为你完成大部分繁重的工作。
阅读更多
利用不同源和接收器进行DOM型XSS利用
原则上,如果存在一条可执行路径,数据可以从源传播到接收器,那么网站就容易受到基于DOM的跨站脚本攻击。在实践中,不同的源和接收器具有不同的属性和行为,这可能会影响可利用性,并决定需要采取什么技术。此外,网站的脚本可能会对数据进行验证或其他处理,在尝试利用漏洞时必须考虑这些处理。有多种与基于DOM的漏洞相关的接收器。详情请参阅这个列表。
document.write
接收器可与script
元素配合使用,因此你可以使用一个简单的有效载荷,如下所示:
LAB
但请注意,在某些情况下,写入document.write
的内容可能会包含一些周围的上下文,在利用时需要考虑到这些上下文。例如,在使用JavaScript有效载荷之前,可能需要关闭一些现有元素。
LAB
innerHTML
接收器在任何现代浏览器上都不接受script
元素,也不会触发svg onload
事件。意味着你需要使用img
或iframe
等替代元素。onload
和onerror
等事件处理器可以与这些元素结合使用。例如:
LAB
第三方依赖中的源和接收器
现代Web应用程序通常使用大量的第三方库和框架构建,这些库和框架通常为开发人员提供额外的功能和能力。重要的是要记住,其中一些也可能是DOM型XSS的潜在源和接收器。
jQuery中的DOM型XSS
如果使用的是jQuery之类的JavaScript库,则要留意是否有可以更改页面上DOM元素的接收器。比如,jQuery的attr()
函数可以更改DOM元素的属性。如果数据是从用户控制的源(如URL)读取的,然后传递给attr()
函数,那么就有可能操纵发送的值,从而导致XSS。例如,下面的JavaScript,它使用URL中的数据更改了锚元素的href
属性:
你可以通过修改URL,使location.search
源包含恶意JavaScript URL来利用这个漏洞。当页面的JavaScript将此恶意URL应用到返回链接的href
后,点击返回链接将执行该URL:
LAB
另一个需要留意的潜在接收器是jQuery的$()
选择器函数,它可以用于向DOM注入恶意对象。
jQuery曾经非常流行,一个典型的DOM型XSS漏洞就是由于网站将该选择器与location.hash
源结合使用,以实现动画或自动滚动到页面上特定的元素而造成的。这种行为通常是使用一个易受攻击的hashchange
事件处理器实现的,类似于以下:
由于hash
是用户可控的,攻击者可以利用它将XSS载体注入到$()
选择器接收器中。较新版本的jQuery已修补了这一特定漏洞,当输入以哈希字符(#
)开头时,将无法向选择器中注入HTML。不过,你仍然可以在实际环境中发现易受攻击的代码。
要真正利用这一经典漏洞,你需要找到一种方法,在不需要用户交互的情况下触发hashchange
事件。其中一个最简单的方法就是通过iframe
传递你的利用:
在这个例子中,src
属性指向一个带有空哈希值的易受攻击的页面。当iframe
加载时,XSS载体会被添加到哈希值中,从而导致hashchange
事件触发。
注意
即使是较新版本的 jQuery,只要你对来自源的输入具有完全的控制,并且该源无需
#
前缀,那么它仍然可能通过$()
选择器接收器而易受到攻击。
LAB
AngularJS中的DOM型XSS
如果使用像AngularJS这样的框架,则有可能在没有角括号或事件的情况下执行JavaScript。当一个网站在HTML元素上使用ng-app
属性时,AngularJS将对其进行处理。在这种情况下,AngularJS将在双花括号内执行JavaScript,双花括号可以直接出现在HTML中,也可以出现在属性内。
LAB
DOM型XSS结合反射和存储数据
一些纯粹基于DOM的漏洞在单个页面内自包含。如果脚本从URL读取一些数据并将其写入到一个危险的接收器,那么漏洞就完全是客户端的。
不过,源并不仅限于浏览器直接暴露的数据,它们也可以来自网站。例如,网站通常会在服务器的HTML响应中反射URL参数。这通常与普通XSS有关,但也可能导致反射型DOM XSS漏洞。
在反射型DOM XSS漏洞中,服务器会处理来自请求的数据,并将数据回显到响应中。反射的数据可能被放置在JavaScript字符串字面值中,或者在DOM的数据项中,如表单字段。然后页面上的某个脚本会以不安全的方式处理反射的数据,最终将其写入到一个危险的接收器。
LAB
网站可能也会将数据存储在服务器上,并在其他地方反射它。在一个存储型DOM XSS漏洞中,服务器从一个请求接收数据,存储它,然后在后续的响应中包含这些数据。后续响应中的某个脚本包含一个接收器,然后该接收器以不安全的方式处理数据。
LAB
哪些接收器可能导致DOM型XSS漏洞?
以下是一些可能导致DOM型XSS漏洞的主要接收器:
以下jQuery函数也是可能导致DOM型XSS漏洞的接收器:
如何防范DOM型XSS漏洞
除了在基于DOM的漏洞中描述的通用措施外,还应避免允许来自任何不受信任的源的数据动态写入到HTML文档。
Last updated