◈ 渗透任务 SPA 单页应用前端安全审计 任务中
你的身份 「暗影安全公司」渗透测试工程师 目标网站 QuickApp SPA 应用 (app.quickapp.example.com) 委托方 QuickApp 开发团队 — 安全审计发现前端路由处理可能存在漏洞 任务目标 验证 URL hash 是否存在 DOM XSS 漏洞

◈ 教程:什么是 DOM 型 XSS?

原理

DOM 型 XSS(DOM-based XSS)的漏洞完全存在于客户端 JavaScript中。 恶意数据不经过服务器,而是在浏览器端通过 JavaScript 直接从 Source 流向 Sink。

Source/Sink 模型:Source 是用户可控的数据入口,Sink 是危险的 DOM 操作。 当 Source 的数据未经处理直接到达 Sink,就产生了 DOM XSS。

与反射型/存储型的区别

  • 反射型/存储型:服务端将数据嵌入 HTML 后返回给浏览器
  • DOM 型:服务端返回的 HTML 是正常的,由客户端 JS 动态修改 DOM 导致漏洞
  • 关键区别:DOM XSS 的恶意数据不经过 HTTP 响应,服务端完全无感知

常见 Source

  • location.hash — URL 的 # 部分
  • location.search — URL 的 ? 参数部分
  • document.referrer — 来源页面 URL
  • window.name — 窗口名称
  • postMessage — 跨窗口消息

常见 Sink

  • innerHTML — 设置元素的 HTML 内容(最常见)
  • outerHTML — 替换整个元素
  • document.write() — 直接写入文档流
  • eval() — 执行 JavaScript 字符串
  • location.href — 页面跳转

漏洞代码分析

// Source: 从 URL hash 获取用户输入
var hash = location.hash.substring(1);

// Sink: 直接写入 innerHTML(危险!)
element.innerHTML = decodeURIComponent(hash);

// 为什么 innerHTML 危险?
// 它会将字符串当作 HTML 解析,包括标签和事件处理器

◈ 练习:触发 DOM 型 XSS

目标:QuickApp SPA 应用 (app.quickapp.example.com) 的页面 JavaScript 会读取 URL 的 # 后面的内容, 并通过 innerHTML 写入 DOM。你的任务是构造包含恶意代码的 hash。
(无 hash 值)
重置
DOM 渲染输出区域(innerHTML Sink):

修改 URL 的 # 部分,内容将在此渲染...
查看漏洞源码 (JavaScript)
// JavaScript 代码(客户端) // 读取 URL hash 并直接写入 innerHTML window.onload = function() { var hash = location.hash.substring(1); // 去掉 # 号 if (hash) { // 危险:用户可控数据直接写入 innerHTML document.getElementById("output").innerHTML = decodeURIComponent(hash); } }; // HTML 结构 // <div id="output"></div>
过滤状态:无任何过滤 — URL hash 经 decodeURIComponent 解码后直接写入 innerHTML