前端如何防止XSS攻击?我用了转义还是被绕过了?
最近在做用户评论功能,后端返回的评论内容里可能包含用户输入的HTML,我用DOMPurify.sanitize()处理了,但测试时发现还是能插入脚本,是不是我用法不对?
比如下面这段代码,我以为会被过滤掉,结果居然执行了:
const dirty = '<img src=x onerror=alert(1)>';
const clean = DOMPurify.sanitize(dirty);
document.getElementById('comment').innerHTML = clean;
我查了文档说默认配置应该能防XSS,但实际在Chrome里弹窗了。是不是还要加什么配置?或者我该换别的方案?
这里我禁用了 img 标签和 onerror 属性作为示例,你可能需要根据实际情况调整这些配置。不过,最安全的做法是尽量避免使用 innerHTML 插入不可信的内容。如果可能的话,考虑使用 textContent 或者创建元素节点的方式来插入内容,这样可以完全避免 XSS 风险。
另外,虽然 DOMPurify 很强大,但安全这块儿没有绝对的银弹,最好还是多一层防御,比如后端也要做相应的过滤和校验。
你传入DOMPurify的是已经HTML实体编码过的字符串
<img src=x onerror=alert(1)>,DOMPurify拿它当普通文本处理,根本不会识别成HTML标签。然后你通过innerHTML赋值时,浏览器自动解码,就成了可执行的
。所以流程反了:要么后端返回原始HTML你自己sanitize,要么前端收到编码后的字符串先解码再sanitize。
最简单的修复:
或者更直接的方式:让后端别返回实体编码的内容,返回原始HTML字符串,然后直接用DOMPurify处理。
另外提醒一下,如果你用的是React或者Vue这些框架,它们的默认渲染机制本身就能避免这类问题,除非你用 dangerouslySetInnerHTML 或者 v-html。