当你的网站被注入恶意脚本,用户数据泄露,你可能会怀疑是输入过滤不够严格。但即使做了输入过滤和输出编码,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-src、script-src、style-src、img-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 的步骤
- 先使用报告模式收集违规,分析现有资源加载。
- 从宽策略开始,如
default-src 'self',逐步添加必要的域名。 - 处理内联脚本:优先改为外部文件,或使用 nonce/hash。
- 测试所有页面功能,特别是第三方脚本(如分析、广告)。
- 在 CDN 或源站启用 CSP,并定期审查日志。
结论:CSP 是 XSS 防御的基石
通过上述配置,你能有效降低 XSS 风险。记住,CSP 并非万能,但结合其他防护措施,能显著提升安全性。持续监控和更新策略是长期维护的关键。
参考资料
- Cloudflare Cache Documentation
- Cloudflare Workers Documentation
- Cloudflare DDoS Protection Documentation
延伸阅读
