1. 网络安全学会
  2. 跨站脚本
  3. 基于DOM

基于DOM的XSS

在本节中,我们将描述基于DOM的跨站点脚本(DOM XSS),解释如何查找DOM XSS漏洞,并讨论如何利用具有不同来源和接收器的DOM XSS。

什么是基于DOM的跨站点脚本?

当JavaScript从攻击者可控制的源(例如URL)中获取数据并将其传递到支持动态代码执行的接收器(例如eval()或innerHTML)时,通常会出现基于DOM的XSS漏洞。 这使攻击者能够执行恶意JavaScript,这通常使他们可以劫持其他用户的帐户。

要进行基于DOM的XSS攻击,您需要将数据放入源中,以便将其传播到接收器并导致执行任意JavaScript。

DOM XSS的最常见来源是URL,通常可以通过window.location对象进行访问。 攻击者可以构建一个链接,以将受害者发送到易受攻击的页面,并在查询字符串和URL的片段部分中添加有效负载。 在某些情况下,例如在针对404页面或运行PHP的网站时,有效负载也可以放置在路径中。

有关源和接收器之间的污染流的详细说明,请参阅基于DOM的漏洞页面。

如何测试基于DOM的跨站点脚本

使用Burp Suite的web漏洞扫描程序可以快速可靠地找到大多数DOM XSS漏洞。 要手动测试基于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调试器来确定是否以及如何将输入发送到接收器。

对于每个潜在的来源(例如位置),您首先需要在页面的JavaScript代码中查找引用来源的案例。 在Chrome的开发人员工具中,您可以使用Control + Shift + F(或在MacOS上为Command + Alt + F)在页面的所有JavaScript代码中搜索源。

找到要读取源的位置后,就可以使用JavaScript调试器添加一个断点,并遵循如何使用源的值。 您可能会发现源已分配给其他变量。 在这种情况下,您将需要再次使用搜索功能来跟踪这些变量,并查看它们是否已传递到接收器。 当您发现一个接收器已分配了源数据,可以使用调试器通过将变量悬停在变量上以显示其值,然后将其发送到接收方来检查该值。 然后,与HTML接收器一样,您需要优化输入以查看是否可以进行成功的XSS攻击。

使用不同的源和接收器利用DOM XSS

原则上,如果存在可执行的路径,数据可以通过该路径从源传播到接收器,则网站很容易受到基于DOM的跨站点脚本的攻击。 实际上,不同的源和接收器具有不同的特性和行为,这些特性和行为会影响可利用性,并确定需要哪些技术。 此外,网站的脚本可能会执行验证或尝试处理利用漏洞时必须容纳的其他数据。 有很多与基于DOM的漏洞相关的接收器。 有关详细信息,请参阅下面的列表。

document.write('... <script>alert(document.domain)</script> ...');

但是请注意,在某些情况下,写入document.write的内容包含一些周围环境,您在利用这些环境时需要考虑这些环境。 例如,在使用JavaScript有效负载之前,您可能需要关闭一些现有元素。

innerHTML接收器不接受任何现代浏览器上的脚本元素,也不会触发svg onload事件。 这意味着您将需要使用其他元素,例如img或iframe。 事件处理程序(例如onload和onerror)可以与这些元素结合使用。 例如:

element.innerHTML='... <img src=1 onerror=alert(document.domain)> ...'

如果使用的是JavaScript库(例如jQuery),请注意可能会改变页面上DOM元素的接收器。 例如,jQuery中的attr()函数可以更改DOM元素上的属性。 如果从诸如URL之类的用户控制源中读取数据,然后将其传递给attr()函数,则可能有可能操纵发送的值以引起XSS。 例如,这里有一些JavaScript可以使用URL中的数据更改锚元素的href属性:

$(function(){
$('#backLink').attr("href",(new URLSearchParams(window.location.search)).get('returnUrl'));
});

您可以通过修改URL来利用此漏洞,以便location.search源包含恶意的JavaScript URL。 页面的JavaScript将此恶意URL应用于反向链接的href后,单击反向链接将执行该恶意URL:

?returnUrl=javascript:alert(document.domain)

如果使用了类似AngularJS的框架,则可以在没有尖括号或事件的情况下执行JavaScript。 当网站在HTML元素上使用ng-app属性时,它将由AngularJS处理。 在这种情况下,AngularJS将在双花括号内执行JavaScript,该花括号可以直接出现在HTML或属性内。

DOM XSS与反射和存储的数据结合

一些纯基于DOM的漏洞是独立包含在单个页面中的。 如果脚本从URL读取一些数据并将其写入危险的接收器,则该漏洞将完全在客户端。

但是,来源不限于浏览器直接公开的数据-它们也可以源自网站。 例如,网站通常在服务器的HTML响应中反映URL参数。 这通常与正常的XSS有关,但也可能导致所谓的反射+ DOM漏洞。

在反射+ DOM漏洞中,服务器处理来自请求的数据,并将数据回显到响应中。 反射的数据可能会放置在JavaScript字符串文字或DOM中的数据项(例如表单字段)中。 然后,页面上的脚本会以不安全的方式处理反射的数据,最终将其写入危险的接收器。

eval('var data = "reflected string"');

网站还可以将数据存储在服务器上,并将其反映到其他位置。 在存储+ DOM漏洞中,服务器从一个请求接收数据,将其存储,然后将数据包括在以后的响应中。 后面的响应中的脚本包含一个接收器,该接收器然后以不安全的方式处理数据。

element.innerHTML = comment.author

哪些接收器可能导致DOM-XSS漏洞?

以下是一些可能导致DOM-XSS漏洞的主要接收器:

document.write()
document.writeln()
document.domain
someDOMElement.innerHTML
someDOMElement.outerHTML
someDOMElement.insertAdjacentHTML
someDOMElement.onevent

以下jQuery函数也是可能导致DOM-XSS漏洞的接收器:

add()
after()
append()
animate()
insertAfter()
insertBefore()
before()
html()
prepend()
replaceAll()
replaceWith()
wrap()
wrapInner()
wrapAll()
has()
constructor()
init()
index()
jQuery.parseHTML()
$.parseHTML()

如何防止DOM-XSS漏洞

除了基于DOM的漏洞页面上描述的常规措施之外,您还应避免允许将来自任何不受信任来源的数据动态地写入HTML文档。