在 Web 安全领域,跨站脚本攻击(XSS)始终位居 OWASP Top 10 前列。根据攻击 payload 的存储与触发方式,XSS 通常被分为反射型、存储型和 DOM 型三类。其中,DOM 型 XSS 因其不依赖服务器端响应、完全在浏览器端触发,成为前端安全中极为隐蔽且危害巨大的一类漏洞。本文将系统介绍 DOM 型 XSS 的挖掘方法,并给出切实可用的前端安全编码实践。
一、DOM 型 XSS 的本质
传统 XSS 的漏洞点位于服务器端:用户输入被拼接进 HTML 响应,浏览器解析后执行恶意脚本。而 DOM 型 XSS 的漏洞点位于 JavaScript 代码中——攻击者通过控制 URL 参数、location.hash、document.referrer 等客户端输入源,将恶意数据传递给危险的内置函数,最终导致脚本执行。
其核心链路为:源(Source)→ 传播路径(Sink)。常见的 Source 包括 location.search、location.hash、document.URL、window.name、postMessage 数据等;常见的 Sink 包括 innerHTML、outerHTML、document.write、eval、setTimeout、setInterval、Function 构造函数、element.setAttribute 等。
二、挖掘 DOM 型 XSS 的实用方法
1. 静态代码审计
首先对前端 JavaScript 文件进行全局搜索,定位所有 Sink 函数。推荐搜索关键词:
innerHTML、outerHTML、insertAdjacentHTMLdocument.write、document.writelneval、Function(、setTimeout(、setInterval(location.href、location.replace、location.assign
找到 Sink 后,逆向追踪其参数是否来自可控 Source。若数据流未经过滤直接进入 Sink,则存在漏洞嫌疑。
2. 浏览器动态调试
打开浏览器开发者工具,在 Sources 面板中对可疑 Sink 函数下断点。操作页面触发交互后,观察调用栈与传入参数。若参数值包含 URL 中的可控部分,即可确认漏洞。
3. 自动化工具辅助
- DOM Invader:Burp Suite 内置插件,可自动标记 Source 与 Sink,并生成 Canary 值验证漏洞。
- XSStrike:支持 DOM 型 XSS 模糊测试。
- Chrome DevTools 的 Coverage 面板:快速定位未使用代码,缩小审计范围。
4. 手工 Payload 验证
针对不同 Sink 构造验证 payload:
- 对于
innerHTML:<img src=x onerror=alert(1)> - 对于
eval:alert(1)// - 对于
setTimeout:alert(1)
注意:现代浏览器对 innerHTML 中的 <script> 标签不执行,但事件属性(如 onerror)仍会触发。
三、前端安全编码实践
挖掘漏洞只是第一步,真正的安全需要从编码阶段杜绝风险。以下为可落地的最佳实践。
1. 优先使用安全的 API
- 使用
textContent代替innerHTML插入纯文本。 - 使用
setAttribute设置属性,避免字符串拼接。 - 使用
document.createElement+appendChild构建 DOM 节点。 - 若必须使用
innerHTML,务必配合 DOMPurify 等库进行净化。
2. 对 URL 参数进行严格校验
不要直接信任 location.search 或 location.hash。使用 URLSearchParams 解析参数,并对内容进行白名单校验。例如,若参数预期为数字,则强制转换并检查 isNaN。
3. 避免危险的动态执行
禁止使用 eval、Function 构造函数执行用户输入。对于 setTimeout 和 setInterval,传入函数而非字符串。
4. 实施内容安全策略(CSP)
CSP 是抵御 XSS 的最后一道防线。建议配置:
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self';
禁止 unsafe-inline 和 unsafe-eval,可有效阻止内联脚本与动态代码执行。
5. 框架层面的防护
现代前端框架(React、Vue、Angular)默认对插值进行转义。但需注意:
- React 中
dangerouslySetInnerHTML是危险入口。 - Vue 中
v-html同样需要谨慎使用。 - Angular 的
bypassSecurityTrust*方法会绕过内置净化,应避免。
6. 安全加固与持续监测
- 对用户输入进行统一编码:HTML 实体编码、JavaScript 转义、URL 编码。
- 设置
HttpOnly和SecureCookie 标志,降低会话劫持风险。 - 集成 SAST 工具(如 ESLint 插件
eslint-plugin-security)在 CI 阶段拦截危险代码。 - 定期进行渗透测试与漏洞扫描,关注 DOM 型 XSS 这一容易被忽略的角落。
四、结语
DOM 型 XSS 的挖掘需要结合静态审计与动态调试,深入理解数据流从 Source 到 Sink 的传播路径。而防御的核心在于:永远不要信任客户端输入,优先使用安全 API,配合 CSP 与框架内置防护,形成纵深防御体系。在 Web 安全形势日益复杂的今天,前端开发者必须将安全编码视为基本素养,而非事后补救。唯有如此,才能从根本上减少 XSS、SQL 注入、CSRF 等各类 Web 安全威胁。
未经允许不得转载:任鹏个人博客 » DOM 型 XSS 的挖掘方法与前端安全编码实践


朋友圈点赞图在线生成源码