免费发布信息
当前位置:APP交易 > 热点资讯 > app交易 >  DOM Clobbering重见天日

DOM Clobbering重见天日

发表时间:2021-07-09 17:11:27  来源:红帽社区  浏览:次   【】【】【
红帽社区是一个垂直网络安全社区,融合“红帽先锋”正能量精神,每日分享最新安全资讯,提供安全问答、靶场、众测、漏洞库等功能,是网络安全爱好者学习、交流的优质社区。

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

作者:Gareth Heyes


随着诸如XSS和CSRF之类的经典客户端漏洞被修复,与CSP和同源相关的漏洞也不再提及,像是DOM Clobbering这样的攻击技术变得越来越重要。最近,在我首次于2013年介绍该项技术后,Michal Bentkowski利用DOM Clobbering攻击了Gmail。在这篇文章中,我会简单介绍一下DOM Clobbering技术,在我原本的研究中加入一些新的技术,同时分享两个交互的实验室,这样你可以自己尝试这些新技术。如果你还不熟悉DOM Clobbering,或许你想先阅读一下Web Security Academy中我们对其的介绍。

确定DOM元素间的关系

首先,获得可以组合在一起的HTML元素列表十分简单。你只需要把两个HTML元素相邻放置,分别为其分配一个ID,然后检查第一个元素是否具有第二个元素的属性。代码如下:

var log=[];
var html = ["a""abbr""acronym""address""""area""article""aside""audio""b""""font""bdi""bdo""""big""""blockquote""body""br""button""canvas""caption""center""cite""code""col""colgroup""command""content""data""datalist""dd""del""details""dfn""dialog""dir""div""dl""dt""element""em""""fieldset""figcaption""figure""font""footer""form""""set""h1""head""header""hgroup""hr""html""i""i""image""img""input""ins""isindex""kbd""keygen""label""legend""li""""listing""main""map""mark""marquee""menu""menuitem""""meter""multicol""nav""nextid""nobr""no""nos""no""""ol""optgroup""option""output""p""param""picture""plaintext""pre""progress""q""rb""rp""rt""rtc""ruby""s""samp""""p""select""shadow""slot""small""source""spacer""span""strike""strong""""sub""summary""sup""svg""table""tbody""td""template""textarea""tfoot""th""thead""time""""tr""track""tt""u""ul""var""video""wbr""xmp"] logs = [];
div=document.createElement('div');
for(var i=0;i<html.length;i++) {
    for(var j=0;j<html.length;j++) {
        div.innerHTML='<'+html[i]+' id=element1>'+'<'+html[j]+' id=element2>';
        document.body.appendChild(div);
        if(window.element1 && element1.element2){
            log.push(html[i]+''+html[j]);
        }
        document.body.removeChild(div);
    }
}
console.log(log.join('\n'));

代码执行结果与预期相似,产生了一个包含与表单相关的元素和图像元素的列表。

form->button
form->fieldset
form->image
form->img
form->input
form->
form->output
form->select
form->textarea

所以,如果你想破坏一个对象的x.y.value值,可以这样做:

<form id=x><output id=y>I've been clobbered</output>
<>
alert(x.y.value);
</>

当然你也可以用我之前的技巧,使用id和name属性组成一个DOM集合。一个DOM集合类似包含多个DOM元素的数组。你可以通过数字索引或其名字访问集合中的元素。

<a id=x><a id=x name=y href="Clobbered">
<>
alert(x.y)
</>

新的DOM Clobbering技术

通过使用带有表单的DOM集合,可以深入破坏三个层次(感谢@PwnFunction的纠正)

<form id=x name=y><input id=z></form>
<form id=x></form>
<>
alert(x.y.z)
</>

在Chrome中,如果在父表单中使用带有表单控件或者图像元素时,你可以将这组元素变成类似数组的对象。Chrome把这类对象标记为[ RadioNodeList],并且可以使用forEach这样数组中存在的方法。

<form id=x>
<input id=y name=z>
<input id=y>
</form>
<>
x.y.forEach(element=>alert(element))
</>

你可能好奇为什么不只使用属性(attributes)。好吧,只有在HTML规范将其定义为有效属性时,该属性才起作用。这就意味着,任何未被定义有效的属性都不具有DOM属性(property),所以是未定义的。例如:

<form id=x y=123></form>
<>
alert(x.y)//未定义
</>

你可以轻易在DOM中搜索可以被破坏的属性:

var html = [...]//HTML元素数组
var props=[];
for(i=0;i<html.length;i++){
    obj = document.createElement(html[i]);
    for(prop in obj) {
        if(typeof obj[prop] === 'string') {
            try {
                props.push(html[i]+':'+prop);
            }catch(e){}
        }
    }
}
console.log([...new Set(props)].join('\n'));

上面的代码会显示为字符串的DOM属性,但是它们不一定可控。如果想要检查它们是否在某种程度上可控,你可以尝试给该属性赋值,并读取该值。

var html = [...]//HTML elements array
var props=[];
for(i=0;i<html.length;i++){
    obj = document.createElement(html[i]);
    for(prop in obj) {
        if(typeof obj[prop] === 'string') {
            try {
                DOM.innerHTML = '<'+html[i]+' id=x '+prop+'=1>';
                if(document.getElementById('x')[prop] == 1) {
                    props.push(html[i]+':'+prop);
                }
            }catch(e){}
        }
    }
}
console.log([...new Set(props)].join('\n'));

在运行上述所有代码时,我注意到结果中的"username"和"password"有两个空白字符串。这些是锚标记的DOM属性,而不是HTML属性。看起来你可以通过锚来控制这些值。通过反复实验,我发现这些属性与FTP URL中的用来提供凭据的用户名、密码部分有关。这也适用于使用@符号提供用户名和密码的HTTP URL。

<a id=x href="ftp:Clobbered-username:Clobbered-Password@a">
<>
alert(x.username)//Clobbered-username
alert(x.password)//Clobbered-password
</>

你可能已经注意到在使用诸如href这样可以被破坏的属性时,浏览器通常会对这些值进行URL编码。想要解决该问题,可以使用不同的协议,例如file:或者其他协议。

<a id=x href="abc:<>">
<>
alert(x)//abc:<>
</>

Firefox还允许你在标签中使用其他协议,该协议会被锚使用,同时允许未编码的值。

< href=a:abc><a id=x href="Firefox<>">
<>
alert(x)//Firefox<>
</>

也可以在Chrome中做同样的事,只不过这次要在标签的href属性中提供你想要的值:

< href="a://Clobbered<>"><a id=x name=x><a id=x name=xyz href=123>
<>
alert(x.xyz)//a://Clobbered<>
</>

我们已经在Web Security Academy中发布了两个基于该技术构建的交互式DOM实验室,你可以自己尝试:

Clobbering to enable XSS lab

Clobbering attributes lab

更新:破坏多于三层

@Terjanq提到,可以使用is和srcdoc破坏多层的属性。因为如果在一个i上设置了name属性,该i真正的contentWindow会分配给这个name中的全局变量,所以该技术是有效的。之后,你就可以将该i中的HTML元素链接在一起。例如:

<i name=a srcdoc="
<i srcdoc='<a id=c name=d href=cid:Clobbered>test</a><a id=c>' name=b>"></i>
<>setTimeout(()=>alert(a.b.c.d)500)</>

你可能已经注意到,该技术需要使用setTimeout函数引发延迟来渲染i。不过我找到了一种不需要timeout的使用i的方法!如果你使用了/元素来导入样式表,这会导致一个小的延迟,从而使i能立即被渲染并被破坏。工作方式如下:

<i name=a srcdoc="
<i srcdoc='<a id=c name=d href=cid:Clobbered>test</a><a id=c>' name=b>"></i>
<>@import '//portswigger.net';</>
<>
alert(a.b.c.d)
</>


责任编辑:
声明:本平台发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。

德品

1377 678 6470