富文本编辑器存储内容后渲染时如何有效拦截XSS攻击?
我在用Quill编辑器实现富文本功能时遇到问题,用户输入的<script>标签在存储到数据库后仍然会被渲染执行。之前用sanitize-html做了过滤,但发现标签被正常保留,而恶意脚本却没被拦截,这是哪里配置错了?
尝试过这样设置白名单:
const options = {
allowedTags: [ 'p', 'img', 'br', 'div' ],
allowedAttributes: {
'img': ['src']
}
};
sanitizeHtml(dirty, options);
但测试时输入<div><script>alert(1)</script></div>,渲染后控制台居然弹窗了,这说明过滤逻辑存在漏洞,该怎么调整配置才能彻底阻断脚本执行?
disallowedTagsMode,导致 script 虽然被“过滤”了,但它的内容可能被保留成纯文本,或者浏览器在某些场景下还能解析。先说结论:前端 sanitize 是第一道防线,但别指望它 100% 靠谱,后端必须再做一层清洗,尤其是入库前。
先看你的问题——你写的
allowedTags里没包含script,按理说应该被删掉,但为什么还能执行?因为
sanitize-html默认disallowedTagsMode: 'escape',会把 script 里的内容转成 HTML 实体,比如<script>alert(1)</script>,这样就安全了。但如果你的
dirty是已经被浏览器解析过一遍的 HTML 字符串(比如你直接用innerHTML插进去过),那 script 标签可能早就执行过了——sanitize 必须在 HTML 还是纯字符串时就做!你现在的风险点有几个:
1. 没配置
disallowedTagsMode,默认是escape,但万一你用了旧版或自定义了行为2. 没禁用危险协议,比如
javascript:、data:text/html这种3. 没处理内联事件,比如
onerror、onload、onclick,这些在 img、iframe、svg 里都能埋雷4. 可能后端没再做一层清洗,直接存了原始 dirty HTML
正确姿势是这样配置
sanitize-html:但重点来了:别只靠前端 sanitize!
后端一定要用类似
DOMPurify的库(Node 环境可以用jsdom + DOMPurify)再过一遍,或者用 Java 的 Jsoup、Python 的 bleach,确保入库前是干净的。另外补充一点:如果你用 Quill,它默认会把 HTML 存成 Delta 格式,但很多人为了方便直接用
editor.getHTML(),这个返回的就是原始 HTML,千万别直接存这个,应该用editor.getContents()得到 Delta,再转成 HTML 时用Delta.toHTML(),但这个方法本身也不安全,还是得再 sanitize。最后说个血泪教训:
XSS 防御永远是“纵深防御”,前端加后端双保险,再配合 CSP header,三重防护才稳妥。
附个 CSP 示例(Nginx 里加):
这样就算漏了点,脚本也跑不起来。
浏览器兼容性基本都 OK,IE 那种老古董不考虑也罢。
sanitize-html的配置上,虽然你定义了白名单标签和属性,但没有处理嵌套的恶意标签。攻击者可以通过将脚本嵌套在合法标签中来绕过过滤规则。比如你提到的<div><script>alert(1)</script></div>,<script>标签被保留了下来。要彻底阻断 XSS 攻击,需要调整配置并加入额外的防护措施。首先,明确一点:
sanitize-html默认不会移除<script>标签,除非你在allowedTags中显式禁止它。其次,仅仅依赖白名单是不够的,还需要结合上下文进行更严格的校验。以下是改进后的代码示例:
这里的关键点在于:
- 设置
disallowedTagsMode为'remove',确保所有不在白名单中的标签被完全移除。- 确保
allowVulnerableTags设置为false,以防止意外允许危险标签。此外,光靠前端或存储前的过滤是不够的,建议在渲染时也做一层防护。比如在输出到页面时,使用安全的编码方式。如果你用的是模板引擎,可以启用自动转义功能;如果是手动拼接 HTML,可以用类似
DOMPurify的库进一步净化内容。最后提醒一下,XSS 防护是个系统工程,除了输入过滤,还要注意 HTTP 响应头的安全配置,比如设置
Content-Security-Policy来限制脚本执行来源。这样即使有漏网之鱼,也能通过 CSP 阻止恶意脚本运行。总之,配置好
sanitize-html是第一步,后续还要结合多层防御机制才能真正降低风险。安全这东西,永远别想着一劳永逸,得时刻保持警惕。