在 Web 应用开发中,富文本编辑器几乎是内容型产品的标配。无论是博客后台、论坛发帖、商品详情编辑,还是企业级 CMS 系统,用户都希望能够像使用 Word 一样对内容进行加粗、变色、插入链接、上传图片等操作。然而,富文本编辑器在带来便利的同时,也打开了一扇通往 XSS(跨站脚本攻击)的大门。
在 web 安全 的众多议题中,xss 长期占据 OWASP Top 10 的重要位置,而富文本编辑器场景下的 XSS 过滤,则是其中最具挑战性的问题之一。本文将从实际场景出发,讨论如何设计一套合理的白名单过滤机制,并顺带梳理 sql 注入、csrf 等常见风险与 安全加固 的整体思路。
一、为什么富文本编辑器是 XSS 的重灾区
普通输入框的 XSS 防御相对简单:对用户输入进行 HTML 实体编码,让 < 变成 <,> 变成 >,浏览器就不会把它当作标签解析。但富文本编辑器恰恰相反——它需要保留一部分 HTML 标签和属性,才能呈现出用户想要的格式。
这就产生了一个核心矛盾:
- 如果全部转义,富文本就失去了意义;
- 如果全部放行,攻击者就可以插入
<script>、<img onerror=...>等恶意代码。
更麻烦的是,富文本内容往往会被存储到数据库,然后在其他用户的浏览器中渲染出来。这意味着一次注入,可能影响所有查看该内容的用户,形成典型的存储型 XSS。
常见的攻击向量包括:
<script>alert(document.cookie)</script><img src=x onerror=alert(1)><a href="javascript:alert(1)">点击</a><svg/onload=alert(1)>- 利用 CSS 表达式或
style属性进行注入
二、黑名单为什么不可靠
很多开发者第一反应是“把危险标签和关键字过滤掉”,也就是黑名单方案。例如屏蔽 <script>、onerror、javascript: 等。但黑名单在富文本场景下几乎注定失败,原因有三:
- HTML 语法过于灵活:大小写混写、属性换行、实体编码、注释穿插,都能绕过简单的字符串匹配。例如
<scr<script>ipt>在部分过滤逻辑下会被还原成<script>。 - 浏览器解析存在容错:浏览器对畸形 HTML 有很强的纠错能力,攻击者可以利用这一点构造出过滤器看不懂、浏览器却会执行的代码。
- 新向量层出不穷:今天屏蔽了
onerror,明天可能又出现新的 SVG 事件或 CSS 注入方式。
因此,安全社区普遍推荐的做法是:白名单机制。
三、白名单设计的核心原则
白名单的核心思想是:只允许明确安全的标签、属性和协议通过,其余一律丢弃或转义。设计时建议遵循以下原则。
1. 标签白名单
只保留富文本必需的标签,例如:
- 文本结构:
p、br、strong、em、u、s、blockquote - 标题:
h1~h6 - 列表:
ul、ol、li - 链接与图片:
a、img - 表格:
table、thead、tbody、tr、th、td - 代码:
pre、code
像 script、iframe、object、embed、form、input 等标签应坚决排除。
2. 属性白名单
不同标签允许的属性应分别定义。例如:
a:只允许href、title、targetimg:只允许src、alt、title、width、height- 全局属性:可考虑
class,但要谨慎,因为class可能配合前端框架造成意外行为
特别注意,所有 on* 事件属性(onclick、onerror、onload 等)必须全部禁止。
3. 协议白名单
对 href、src 等 URL 属性,必须校验协议。只允许:
http:https:mailto:- 相对路径(如
/images/a.png)
坚决禁止 javascript:、data:(除非明确需要且经过严格处理)、vbscript: 等。
4. 样式处理
style 属性是另一个高风险点。如果业务不需要自定义样式,建议直接禁止。若必须保留,应只允许有限的 CSS 属性(如 color、font-size、text-align),并过滤 expression、url()、behavior 等危险值。
四、实现建议与工具选择
在实际工程中,不建议自己从零编写正则过滤器。推荐使用成熟的安全库:
- 前端:DOMPurify 是目前最广泛使用的方案,支持自定义白名单,能有效处理各种浏览器解析差异。
- 后端:Java 可使用 OWASP Java HTML Sanitizer,PHP 可使用 HTMLPurifier,Python 可使用 bleach。
典型流程是:前端用 DOMPurify 做即时预览过滤,后端在入库前再做一次严格过滤。永远不要只信任前端,因为攻击者可以直接构造请求绕过浏览器。
此外,还要注意:
- 过滤应在服务端作为最后一道防线;
- 富文本内容在输出到页面时,根据上下文选择正确的编码方式;
- 配合 CSP(内容安全策略),限制内联脚本执行,进一步降低 XSS 影响。
五、与 SQL 注入、CSRF 的关系
虽然本文聚焦 XSS,但在 web 安全 体系中,各类风险往往相互关联。sql 注入 通过拼接恶意 SQL 语句窃取或篡改数据,防御的核心是参数化查询;csrf 则利用用户已登录状态伪造请求,防御手段包括 CSRF Token、SameSite Cookie 等。
一个完整的 安全加固 方案,通常包括:
- 输入校验与输出编码
- 富文本白名单过滤
- 参数化查询防 SQL 注入
- CSRF Token 与 SameSite 策略
- 最小权限原则与安全响应头
- 定期安全测试与代码审计
六、总结
富文本编辑器场景下的 XSS 过滤,本质上是在“功能”与“安全”之间寻找平衡。黑名单看似简单,实则漏洞百出;白名单虽然实现成本更高,但能从根本上限制攻击面。设计时应明确标签、属性、协议三层白名单,借助成熟库完成过滤,并在服务端保留最终校验。
安全从来不是单一措施能够解决的,只有把 XSS 过滤、SQL 注入防护、CSRF 防御以及整体安全加固结合起来,才能构建真正可靠的内容型 Web 应用。
未经允许不得转载:任鹏个人博客 » 富文本编辑器场景下的 XSS 过滤与白名单设计


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