XSS 防护清单是什么
实践中的 XSS 防护分三层:默认转义、必要时的输入净化、运行期缓解。默认转义指模板引擎与前端框架在输出位置自动编码,这是覆盖面最广的一层;输入净化只用于确实需要保留 HTML 的场景,例如富文本编辑与 Markdown 渲染,必须用白名单库限定标签与属性;运行期缓解包括 Cookie 的 HttpOnly 标志与内容安全策略,它们不修复注入点,但能把单点问题的影响范围压小。三层叠加后,即使某一层出现遗漏,攻击也未必能落地。
基本信息
| 防护层次 | 默认转义、输入净化、运行期缓解 |
|---|---|
| 默认转义范围 | 模板引擎与前端框架的插值位置 |
| 净化适用场景 | 富文本、Markdown、允许保留格式的提交内容 |
| 净化方式 | 标签与属性白名单,禁用内联事件与危险协议 |
| 运行期缓解 | Cookie 加 HttpOnly 与 SameSite、部署内容安全策略 |
| 验证要求 | 覆盖页面、JSON 接口、导出文件与邮件模板等多个出口 |
典型场景
- 普通表单与列表展示:依赖模板引擎默认转义即可覆盖
- 富文本编辑器内容:需要白名单净化后再存储与展示
- 单页应用从接口取数据插入 DOM:注意显式绕过接口
- 后台运营查看用户提交内容:管理员会话权限高,需重点防护
- 导出文件与邮件模板:同样属于输出位置,转义规则独立
- 第三方内容嵌入:评估来源可信度并加策略限制
三层防护要点
三层防护要点
1. 输出层:模板引擎默认转义开启(Jinja2 autoescape、Thymeleaf 等)
2. 富文本:服务端用白名单库净化(标签与属性白名单)
3. 缓解层:会话 Cookie 加 HttpOnly;部署 CSP;敏感页面禁止被嵌套
4. 前端:避免 innerHTML 与 eval 类接口处理不可信数据
# 净化只在存储与展示链路做一次是不够的:展示位置不同,编码规则不同CSP 响应头示例
CSP 响应头示例
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'none'" always;
# 上线前先用 Content-Security-Policy-Report-Only 收集违规来源
# 严格策略可能影响第三方统计与客服脚本,需与业务方确认清单防护层与作用范围
| 层次 | 手段 | 能防住什么 |
|---|---|---|
| 默认转义 | 模板与框架自动编码 | 绝大多数插值位置的注入 |
| 输入净化 | 白名单标签与属性 | 富文本场景下的恶意标记 |
| Cookie 标志 | HttpOnly 与 SameSite | 脚本读取会话与跨站自动携带 |
| 内容安全策略 | 限制脚本与资源来源 | 内联脚本执行与外部脚本加载 |
| 框架嵌套控制 | 禁止被其他站点嵌套 | 点击劫持类风险 |
内容安全策略可先用 Report-Only 模式收集违规报告,确认没有误杀后再切换强制模式。
富文本净化的白名单要定期复核:编辑器升级后可能新增标签与属性需求,宽松处理会悄悄放大风险。