Web 安全

CSP (内容安全策略)

约 4 分钟阅读

什么是 CSP (Content Security Policy)

CSP (Content Security Policy) 是一种 HTTP 响应头,允许服务器控制网页可以加载资源 (脚本、样式表、图片、字体等) 的来源。由于浏览器会阻止加载或执行 CSP 不允许的资源,因此可以大幅缓解 XSS (跨站脚本攻击) 的危害。

XSS 的根本防御措施是输出转义,但实现上的遗漏无法完全消除。CSP 作为纵深防御的一层,发挥着「即使存在 XSS 漏洞,也不让攻击者的脚本执行」的作用。它是安全头中最强大且最复杂的头之一。

主要指令

CSP 由多个指令组成,为每种资源类型指定允许的来源。

  • default-src:其他指令未明确指定的资源的默认策略。default-src 'self' 仅允许来自同源的资源
  • script-src:控制 JavaScript 的加载来源。XSS 防御的核心指令。避免使用 'unsafe-inline',推荐使用 nonce 或 hash
  • style-src:控制 CSS 的加载来源
  • img-src:控制图片的加载来源
  • connect-src:控制 fetch、XMLHttpRequest、WebSocket 的连接目标
  • font-src:控制 Web 字体的加载来源
  • frame-src:控制 iframe 的嵌入来源。也与点击劫持防御相关
  • frame-ancestors:控制哪些父页面源可以将本站嵌入 iframe。是 X-Frame-Options 的后继

源值的指定方式

  • 'self':同源
  • 'none':全部阻止
  • 'nonce-{random}':仅允许具有特定 nonce 值的内联脚本/样式
  • 'strict-dynamic':也允许由 nonce 许可的脚本动态加载的脚本
  • 具体域名:https://cdn.example.com

分阶段部署步骤

CSP 的部署应循序渐进,避免破坏现有站点。

步骤 1:使用 Report-Only 模式监控

使用 Content-Security-Policy-Report-Only 头可以检测并报告策略违规,但不会阻止资源。首先使用此模式了解站点当前加载了哪些资源。

步骤 2:制定基础策略

根据报告分析结果,将必要的资源来源添加到白名单。从宽松的策略开始,逐步收紧。

步骤 3:生产环境部署与持续监控

切换到 Content-Security-Policy 头进行生产部署。通过 report-urireport-to 指令持续收集违规报告,应对误报和新的资源需求。

推荐的严格策略示例

default-src 'none'; script-src 'self' 'nonce-{random}' 'strict-dynamic'; style-src 'self' 'nonce-{random}'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'

此策略通过 nonce 控制内联脚本,并使用 'strict-dynamic' 允许动态加载的脚本。

CSP 与其他安全头的协同

CSP 本身已很强大,但与其他安全头结合可以构建更坚固的防御。

  • HSTS 配合:强制 HTTPS,防止通过中间人攻击篡改 CSP 头。HTTPS 是发挥 CSP 最大效果的前提
  • X-Content-Type-Options: nosniff:防止 MIME 类型嗅探,阻止不应被解释为脚本的资源执行
  • CORS 的关系:CSP 控制资源的加载来源,CORS 控制跨源请求的访问权限。两者是互补关系

CSP 的部署有初始成本,但能大幅提升对 XSS点击劫持的防御能力。在新项目中从开发初期就将 CSP 纳入设计,比后期引入可以大幅降低成本。

常见误解

设置了 CSP 就不需要 XSS 防御措施了
CSP 是缓解 XSS 危害的纵深防御的一层,不能替代 XSS 的根本防御措施 (输出转义)。CSP 的绕过技术也在被研究中,建议同时实现输出转义和 CSP。
CSP 配置太难,小型站点不需要
即使是小型站点也存在 XSS 风险。从最小策略 (例如 default-src 'self'; script-src 'self') 开始,部署很容易。可以通过 Report-Only 模式确认影响,逐步收紧。
分享

相关术语