0 1
前言
最近看到好多师傅都已经学习过了DOM Clobbering Attack,因此自己也来学习一波。
0 2
0x01 简介
DOM最初诞生的时候没有一个很好的标准,以至于各个浏览器在实现的过程中会支持DOM的一些怪异行为,而这些行为可能会导致DOM Clobbering的发生浏览器可能会将各种DOM元素的name和id属性添加为document的属性或页面的全局变量,这会导致覆盖掉document原有的属性或全局变量,或者劫持一些变量的内容。
测试环境 Chrome 80.0.3987.132
0 3
0x02 简单的例子
1.对象创建
测试代码如下:
打印的结果如下:
通过上面的结果,可以看出来HTML标签中的id属性值被当做全局变量,name属性值被当成document的属性,这也就是为什么上面有一行输出undefined的原因。
2.方法的覆盖
测试代码如下:
结果如下:
通过上面的输出结果显示我们可以通过name属性覆盖document中的内置方法。
3.通过标签的层级关系构造变量的层级关系
测试代码如下:
结果如下:
通过上面的结果我们看到,可以通过多层覆盖的方式,覆盖Window和document下的对象。
0 4
0x03 java Scope
由于DOM Clobbering Attack的攻击中有很多的地方用到了java的作用域链,因此我们可以来了解一下:
1.全局作用域:
在java中全局作用域一般是window(nodejs是global)。
2.显示声明:
3.隐式声明:
不带有声明关键字的变量,js会默认帮你声明一个全局变量:
变量result被挂载到了window对象上了。
4.块级作用域:
在 ES6 之前,是没有块级作用域的概念的。如果你有 C++ 或者 Java 经验,想必你对块级作用域并不陌生:
从上面的结果来看,说明var声明的变量,在for循环之后仍然保存在这个作用域里,而for{}仍然在全局作用域里,因此var声明的变量在全局作用域里。
我们可以通过let(或const用来声明常量)来声明变量,实现块级作用域。
除了上面的几种作用域外还有语法作用域,动态作用域等,就不赘述了感兴趣的参考下面的链接。
0 5
0x04 攻击方法
1.为了分析DOM Clobbering漏洞,假设如下代码:
如果我们想利用Dom Clobbering技巧来执行任意的js,需要 解决两个问题:
1)利用html标签的属性id,很容易在window对象上创建任意的属性,但是我们能在新对象上创建新属性吗?
2)怎么控制DOM elements被强制转为string之后的值,大多数的dom节点被转为string后是[object HTMLInputElement]。
我们可以用前面的例子来解决第一个问题:
我们可以用下面的一段代码来枚举,html存在的所有标签,然后检查其dom节点对象有没有实现toString方法,或者是继承于Object.ptototype。如果是继承自Object.prototype,那么很有可能只会返回[object SomeElement]
我们可以得到两个对象:
HTMLAreaElement(<area>)和 HTMLAnchorElement (<a>), 这两个标签的toString会直接返回他的href属性。
结合上面的两个问题,我们会构造如下payload:
但是test1.test2是undefined,这是因为<input>元素会变成<form>的属性,但<VUKDqmza;a>标签并不会。
我们可以通过构造一个HTMLCollection来解决问题,例如:
返回的集合如下所示:
HTMLCollection可以通过index访问,同时可以使用id访问,并且可以使用name访问,例如:
因此上面的问题得到解决,通过构造如下payload:
`<a id="test1"></a><原由网a id="test1" name="test2" href="jaca:alert(1)"></a> `
成功执行。
2.确定DOM元素间的关系
我们把两个HTML元素相邻放置,分别为其分配一个ID,然后检查第一个元素是否具有第二个元素的属性。代码如下:
上面是我们用html标签的id属性来寻找DOM之间的关系的过程,结果如下:
如果我们要覆盖一个对象的x.y.value值,可以用下面的这种方式:
3.使用form标签来伪造三层的对象引用
在Chrome中,当form标签有两个一样的id的input标签时,Chrome会将其处理为[object RadioNodeList],这个可以用forEach来遍历:
4.是否自定义的DOM节点也具有上面的属性呢?
我们可以通过下面的代码来测试一下dom中有哪些属性可以用:
上面的代码显示的是string类型的属性,他们并不一定可控,为了检查他们是否可读写,我们可以用下面的代码:
通过上面的输出结果可以有:
对于上面的DOM属性中,我们需要关注的是username和password属性,他们是a标签的节点属性并不是html中定义的属性,这两个属性可以通过url的中的username字段和password字段提供,但是需要有@符号:
上面不仅可以用ftp协议,也可以用http协议(必须加//),需要注意的是,如果我们直接通过toString函数将dom转换为字符串他的href是经过url编码的,不过我们可以通过一个不存在的协议绕过abc:<>:
5.获取3级以上的对象引用
https://twitter.com/terjanq提到,可以结合iframe的srcdoc属性构造任意层数的对象引用。
例子如下:
上面用到了setTimeout设置一个定时器是为了保证iframe框架的加载完成。我们可以利用style/link来加载外部样式表来造成延迟:
0 6
0x05 攻击实例
1. clobbering to enable XSS lab
实验之前先看一个简单的例子:
这个实验就有点类似下面这个例子:
通过查看源代码我们可以看到这个文件:loadCommentsWithDomClobbering.js,我们可以看到下面的获取图片src的代码:
avatar的默认值是/resources/images/avatarDefault.svg,我们可以通过覆盖window.defaultAvatar来实现xss,构造的payload如下VUKDqmza:
插入的标签如下:
为什么我们要把闭合前面的"编码为",因为cid是没有这个协议的,因此不会对"进行url编码。这样在解码时"就变成了控制字符"改变页面结构。
然后再评论一次,刷新全局变量,加载loadCommentsWithDomClobbering.js即可导致xss。
2.Clobbering attributes lab
实验之前我们先来看一个例子:
// 过滤用户提交的HTML代码,如果包含onclick, ,删掉该属性(attribute)letblockAttributes = [ "onclick", ""]; functionformSubmit( ) { letf = document.getElementById( "form1"); letsandbox = document.implementation.createHTMLDocument( ''); letroot = sandbox.( "div"); root.innerHTML = f.payload.value;
DomBFS(root, function( element) { // 遍历属性名for( vara = 0; a < element.attributes.length; a+= 1) { letattr = element.attributes[a]; if(blockAttributes.indexOf(attr.name) != -1) { element.removeAttribute(attr.name);a -= 1; }}});document.body.(root); }</ > </ body> </ html>
payload如下:
由于attributes被覆盖导致执行到payload的form时跳过for循环跳过黑名单,成功执行xss。
跟上面一样我们先看看loadCommentsWithHtmlJanitor.js的代码。
if(shouldRejectAttr(attr, allowedAttrs, node)) { node.removeAttribute(attr.name);// Shift the array to continue looping.a = a - 1; }}
结合上面的例子我们可以通过构造<form id=x><input id=attributes>的形式来绕过。
根据题目的要求,需要访问触发,并且通过参考资料得知利用tabindex属性和form的onfocus来执行xss。
因此构造如下:
但是我们要解决这个lab需要提交到该漏洞利用的漏洞服务器,而且用户直接点击是不会触发xss的,因此我们要构造一个在评论后主动访问并且加上#x,为了等待评论完成我们需要延迟一下,因此构造下面的payload:
直接提交完成lab。
0 7
0x06 总结
现在一般可以xss的地方都会有过滤,因此当我们xss不了的时候我们是不是可以考虑一下DOM Clobbering Attack呢?
0 8
0x07参考链接
http://d1iv3.me/2018/04/11/DOM-Clobbering-Attack/
https://wonderkun.cc/2020/02/15/DOM%20Clobbering%20Attack%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/
https://portswigger.net/research/dom-clobbering-strikes-back
https://xz.aliyun.com/t/7346
https://portswigger.net/web-security/dom-based/dom-clobbering
WebGoat之XSS
http://hetianlab.com/expc.do?ce=bda568d3-a31c-49ef-ba3e-a4c7d4ee1d0a
(由于html和js都是解释执行的,如果对用户的输入过滤不够严格,导致用户输入一些html或者js代码被浏览器执行)