导语:在我们的认知中,最常见的XSS(Cross-Site Scripting,跨站点脚本)类型是基于源代码的,这意味着注入的JavaScript代码来自服务器端并在客户端执行。

DOM-model.svg_.png

在我们的认知中,最常见的XSS(Cross-Site Scripting,跨站点脚本)类型是基于源代码的,这意味着注入的JavaScript代码来自服务器端并在客户端执行。

但还有另一种主要类型,即基于DOM的类型,其中注入的恶意输入不是通过反射或存储方式从服务器发出的:XSS是由本地JavaScript代码在客户端生成的。

基于DOM的XSS也有反射和存储子类型的功能,非常类似于基于源的XSS。它们都是由浏览器本身通过其JS引擎和客户端存储提供反射和存储。

然而,与简单的请求/响应模型不同,基于DOM的XSS可能需要对代码流进行大量分析才能捕捉到它。对于静态甚至动态分析工具来说,很难发现这个缺陷。

Sources and Sinks/源和库

DOM(Document Object Model,文档对象模型)是通过使用JavaScript代码从服务器(源代码)接收到的HTML文档上构建的结果程序。正如你可能知道的那样,这些代码通过脚本块和/或导入的库嵌入到HTML文档中。JavaScript代码将所有HTML元素转换为对象,并可以对其进行操作,从而在运行时以任何可能的方式更改文档。

我们在客户端拥有与服务器端几乎相同的XSS逻辑:我们需要对输入的东西和输出的东西采用不同的负责方式。在服务器端,我们有PHP语言输入的$ _GET [“var”]或$ _POST [“var”],和输出的echo或print命令,以使我们的XSS情况出现。

在客户端代码中,我们有源代码和接收器。把源当作我们的输入,把库当作我们的输出。源是像在服务器端XSS中一样的对象属性,比如document.location(位置)、document.referrer(引用)、 window.name(名称),甚至在处理之后的URL参数。这个列表非常庞大,因为所有东西都可以由JavaScript处理,并成为一个潜在的接收器源。

因此,为了使我们的基于DOM的XSS研究更加简单,让我们先看看库,因为只有三种主要情况。下面是一个演示它们的页面。

https://brutelogic.com.br/tests/sinks.html

The 3 Sinks/常见的三种库

在我们的演示页面中,我们有以下源代码:

dom-based-source-full.png

它只有一个元素,一个段落由页面唯一的脚本块中的本机JavaScript代码动态更新。没有导入,也没有库。通过3行注释突出显示全部的3个案例,以定义负责每个案例的代码片段的起始位置。

在第一种情况Document Sink之前,我们的代码从API开始,以便能够处理URL参数的值:在获取了文档位置的搜索属性(它本身就是文档的属性)之后,我们创建了一个实现URLSearchParams的新对象。

dom-based-source-get-api.png

Document Sink/文档库

在文档库中,本机JavaScript代码使用攻击者控制或提供的数据更新当前文档。它使得在DOM中插入一个带有javascript代码的全新HTML标记或属性成为可能,该属性可能是一个带有JS代码的事件处理程序。

dom-based-document-sink.png

URL参数“name”的值存储在“username”变量中,以便以后更新文档时使用。如果该变量不是NULL,则使用内容“Hello”和URL中通过“name”参数提供的内容来更新段落元素。这使得攻击者可以通过以下命令插入HTML代码:

https://brutelogic.com.br/tests/sinks.html?name=<img+src+onerror=alert(1)>

在这里需要注意的是,经典的“<script> alert(1)</ script>”不起作用,还有其他几个XSS向量,因为它是一个DOM插入而不是简单的源反射,只有少数会像上面提供的那样工作。

文档接收器可以以多种方式出现:使用innerHTML和outerHTML元素属性,使用document.write(),document.writeln()函数以及JavaScript库提供的任何其他方式来更新元素或文档。

Location Sink/位置库

在位置库中,本地javascript代码通过攻击者控制或提供的数据更新文档的位置。这样,就可以使用现代浏览器的有趣特性:javascript伪协议。

dom-based-location-sink.png

通过使用“redir”参数的值,上面的代码可以将浏览器重定向到另一个地址,加载另一个文档。如果我们使用一个我们控制的站点,那么攻击目标应用程序是毫无用处的,因为我们将脱离上下文。

但是,使用javascript伪协议,它是将javascript代码直接运行到浏览器地址栏中的,所以可以通过当前文档及其上下文运行代码。

https://brutelogic.com.br/tests/sinks.html?redir=javascript:alert(1)

过去,当使用应用程序过滤器和WAFs(web应用程序防火墙)标记“javascript”关键字时,使用数据Uri代替了这一操作。但是现在现代浏览器为js执行提供了一个空白上下文,或者不再允许导航作为安全措施。

Execution Sink/执行库

在执行库中,本地javascript代码通过攻击者控制或提供的数据更新自己的代码流。

dom-based-execution-sink.png

通常,评估库会成为上述大型复杂代码的一部分,我们将看到一个非常简单的代码:其中有3个变量,每个有一个库存指数:Nasdaq, Dow Jones and S&P 500。我们不能认为它们的值来自于实际应用程序中的数据库,因此它们不会一直变化。

创建“market”对象。从url获取“index”参数值 (知道要查找哪个索引)之后,我们尝试确保它是一个字符串,它是一个带有tostring()转换的字符串(只是一个的愚蠢方法来试图避免其结果)。然后,我们的代码在对象“market”中创建属性“index”,动态地使用“eval”函数。 最后,查询索引的当前值显示在段落中。

攻击者可以通过提供他/她想要运行的js代码来简单地实现XSS攻击:

https://brutelogic.com.br/tests/sinks.html?index=alert(1)

因为代码会直接进行评估,所以很简单。在现实世界的应用程序中,很可能需要根据代码流程进行一些测试或分配才能到达有缺陷的点。

除了“eval”之外的其他执行库是“setInterval”和“setTimeout”函数和模板文本。

这些就是我们在寻找基于DOM的XSS时应该注意的三种案例。

源链接

Hacking more

...