DOM型XSS漏洞源于前端脚本将用户可控数据未经安全处理直接写入innerHTML、v-html、dangerouslySetInnerHTML等敏感位置,导致恶意代码在浏览器端执行,完全不依赖服务器反射或存储。

直接用浏览器开发者工具检查 innerHTML 赋值、v-html、dangerouslySetInnerHTML 三处,90% 的 XSS 漏洞当场暴露——不需要等扫描器报错,也不必翻后端代码。
怎么一眼识别高危 HTML 渲染点
前端代码里真正危险的不是“有没有用户输入”,而是“输入是否被当代码执行”。重点盯住三类写法:
-
el.innerHTML = data.content或document.write():原生 JS 最常见裸奔写法 -
<div v-html="article.body"></div>:Vue 项目里最常被忽略的雷区,尤其在富文本展示页 -
<div dangerouslySetInnerHTML={{ __html: props.html }}></div>:React 项目中显式放弃框架防护的信号
注意:textContent、innerText、v-text、{{ }} 插值默认转义,不在此列。但若后续又用 innerHTML 二次拼接,风险照旧。
反射型 XSS 最快验证方式:改 URL 参数 + 看响应体
很多反射型漏洞根本不用开 Burp,手动构造就能确认。打开一个疑似回显参数的页面(如搜索页、错误提示页),在地址栏末尾加参数:
立即学习“前端免费学习笔记(深入)”;
- 先试
?q=<img+src=x+onerror=alert(1)>,看是否弹窗 - 再试
?id=1<script>fetch('/api/me')</script>,用 Network 面板查是否发出了额外请求 - 关键看响应 HTML 中,你的 payload 是否原样出现在
<script>标签外、且未被编码(比如显示为<script></script>就安全)
如果 payload 出现在 <title>、<meta name="description">、onclick= 属性里,说明上下文不同,需针对性闭合,不能只靠通用 payload。
DOMPurify 配置最容易踩的三个坑
装了 DOMPurify 不等于安全,配置错等于白装。常见误操作:
- 用
FORBID_TAGS: ['script']黑名单模式:攻击者换用<svg onload=alert(1)>或<body onload=...>直接绕过 - 没限制协议,只留
a标签却允许href="javascript:alert(1)":必须加ADD_ATTR: ['href', 'src']和ADD_TAGS: ['a', 'img']后,再调用safelist.addProtocols('a', 'href', 'https', 'http') - 对富文本字段用默认配置但没声明
ALLOWED_ATTR: ['class', 'style']:一旦开了style,就可能触发 CSS 注入(如background: url(javascript:...))
生产环境起步建议:用 DOMPurify.sanitize(dirty, {ALLOWED_TAGS: ['p','br','strong','em','a','img'], ALLOWED_ATTR: ['href','src','alt','class'], FORBID_TAGS: ['script','iframe','base']}),再逐项放开,而不是一上来就 SAFE_LIST: []。
服务端 HTML 净化为什么不能用 String.replace
Java/Python/Node.js 里用正则或 replace('<script>', '') 处理用户提交的 HTML,是典型无效防御。原因很实在:
- 大小写混淆:
<ScRiPt>、<SCRIPT>、<script//>全部逃逸 - 注释绕过:
<!--<script>--><script>在解析时会被还原 - Unicode 变体:
<script></script>、<script></script>在浏览器里照样执行
正确做法:Java 用 jsoup.Cleaner + Safelist.basicWithImages();Node.js 用 DOMPurify.sanitize()(服务端渲染时);Python 用 bleach.clean() 并显式指定 tags 和 attributes。记住:净化必须基于真实 HTML 解析器,不是字符串层面的“找-删”。
真正的难点不在“会不会配 DOMPurify”,而在于分清哪些字段是“纯文本”、哪些是“带格式 HTML”、哪些压根不该进 HTML 流程——同一个用户昵称字段,在评论列表里用 textContent 显示,在后台编辑页里却用 v-html 渲染,这种混用才是多数 XSS 的根源。



















