内容安全策略CSP配置指南:有效防御XSS

内容安全策略CSP是防御XSS的关键手段。本文从实际问题出发,讲解如何配置CSP指令、处理CDN缓存影响、使用nonce与hash,并解决常见误区,助你有效防护。

内容安全策略CSP配置指南:有效防御XSS
封面图:ZuCDN · ZuCDN 原创

当你的网站被注入恶意脚本,用户数据泄露,你可能会怀疑是输入过滤不够严格。但即使做了输入过滤和输出编码,XSS 攻击仍可能绕过。内容安全策略CSP(Content Security Policy)是浏览器提供的一层关键防线,通过明确指定允许加载的资源来源,阻断恶意脚本的执行。本文将直接面对配置 CSP 时的常见问题,提供可操作的排查与配置步骤。

问题:CSP 配置后页面功能失效,如何定位原因?

很多开发者配置 CSP 后,发现内联脚本、样式或图片加载失败。这是因为 CSP 默认禁止 inline 脚本和样式,以及 eval 等动态执行。此时,浏览器控制台会显示具体的违规报告,例如 Refused to execute inline script because it violates the following Content Security Policy directive。你需要根据报告逐项调整策略。

使用报告模式(Content-Security-Policy-Report-Only)

在正式启用前,先使用 Content-Security-Policy-Report-Only 响应头,它不会阻止资源加载,只报告违规。通过 Cloudflare 缓存 或源服务器配置该头,收集违规报告,再逐步收紧策略。注意,报告模式不会影响功能,但能让你提前发现潜在问题。

关键:CSP 指令如何正确设置?

核心指令包括 default-srcscript-srcstyle-srcimg-src 等。推荐配置:

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:;

这里 'self' 允许同源资源,'unsafe-inline' 允许内联样式(但避免用于脚本)。如果你需要内联脚本,可以使用 'unsafe-inline' 或更安全的 nonce/hash 机制。

使用 nonce 或 hash 允许特定内联脚本

为每个请求生成唯一的 nonce(随机数),并注入到脚本标签中:

<script nonce="random123">...</script>

CSP 头中设置 script-src 'nonce-random123'。同样,hash 允许你指定脚本内容的哈希值。这比 'unsafe-inline' 安全得多,因为它只允许你指定的脚本执行。

误区:CSP 与 CDN 缓存冲突如何解决?

使用 Cloudflare 缓存 时,CSP 头可能被缓存,导致不同用户收到相同的 nonce,从而失效。解决方法是:确保 CSP 头不被缓存,或使用动态 nonce 时设置 Cache-Control: no-cache 或使用 Cloudflare Workers 在边缘动态生成 CSP 头。

通过 Workers 动态生成 CSP

Cloudflare Workers 允许你在边缘修改响应头。以下是一个示例:

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  const response = await fetch(request)
  const newHeaders = new Headers(response.headers)
  newHeaders.set('Content-Security-Policy', "script-src 'self' 'nonce-" + generateNonce() + "'")
  return new Response(response.body, {
    status: response.status,
    headers: newHeaders
  })
}

这样每个请求都有独立的 nonce,避免缓存问题。同时,Workers 可以集成更多安全逻辑,如 DDoS 防护(参考 Cloudflare DDoS 防护

排查:CSP 如何与现有安全措施配合?

CSP 不是孤立的,应与输入过滤、输出编码、HttpOnly Cookie 等配合。若你已部署了其他响应头(如 X-Frame-Options),可参考 Web安全响应头配置指南。同时,理解 XSS攻击原理 有助于你评估 CSP 的覆盖范围。

失败条件:CSP 无法防御哪些攻击?

CSP 无法防御 DOM-based XSS,如果恶意代码通过 DOM 操作动态插入脚本,且未受 CSP 限制(如使用 eval 且未禁止),则可能绕过。因此,仍需严格输入验证。此外,CSP 头本身可能被剥离,需配合 HTTPS 和 HSTS 防止中间人攻击。

实践:逐步部署 CSP 的步骤

  1. 先使用报告模式收集违规,分析现有资源加载。
  2. 从宽策略开始,如 default-src 'self',逐步添加必要的域名。
  3. 处理内联脚本:优先改为外部文件,或使用 nonce/hash。
  4. 测试所有页面功能,特别是第三方脚本(如分析、广告)。
  5. 在 CDN 或源站启用 CSP,并定期审查日志。

结论:CSP 是 XSS 防御的基石

通过上述配置,你能有效降低 XSS 风险。记住,CSP 并非万能,但结合其他防护措施,能显著提升安全性。持续监控和更新策略是长期维护的关键。

参考资料

延伸阅读