CSP
本文约需 2 分钟阅读
CSP (Content Security Policy) 是一种通过 HTTP 响应头声明允许在网页上执行的资源来源的安全机制。作为大幅降低跨站脚本 (XSS)危害的防御层,它于 2012 年在 W3C 标准化。服务器向浏览器指示「本页面只允许执行该域名的脚本」,从而在浏览器层面阻止攻击者注入的恶意脚本执行。
作为 XSS 对策的定位
XSS 对策的基础是输入的净化和输出的转义,但这些对策容易因开发者的失误而出现疏漏。 CSP 作为补充这些对策的「最后一道防线」发挥作用。即便因转义疏漏使攻击代码混入 HTML,只要 CSP 设置正确,浏览器就会拒绝执行该脚本。将安全编码与 CSP 结合,即可实现纵深防御。
主要指令
| 指令 | 控制对象 | 设置示例 |
|---|---|---|
| default-src | 其他指令的回退 | 'self' |
| script-src | JavaScript 的加载与执行 | 'self' 'nonce-abc123' |
| style-src | CSS 的加载与应用 | 'self' 'unsafe-inline' |
| img-src | 图像的加载源 | 'self' data: https://cdn.example.com |
| connect-src | fetch / XHR / WebSocket 的连接目标 | 'self' https://api.example.com |
| frame-ancestors | 允许以 iframe 嵌入的来源 | 'none' |
| form-action | 表单的提交目标 | 'self' |
基于 nonce 与基于 hash 的许可方式
允许内联脚本的方法有 nonce 方式和 hash 方式两种。
服务器为每个请求生成一个随机值 (nonce),并在 CSP 头和 script 标签中嵌入相同的值。只有值一致的脚本才会被执行。它适合动态页面,且 Next.js、Rails 等框架支持自动生成 nonce。
从内联脚本的内容计算出 SHA-256 等哈希值,并写入 CSP 头。脚本内容哪怕变动一个字节,哈希就会不匹配而无法执行。它适合静态脚本,但每次更改内容都需要重新计算哈希。
通过 report-uri / report-to 进行监控
CSP 内置了向服务器报告策略违规的机制。report-uri (旧规范) 或 report-to (新规范) 指令指定报告发送目标后,浏览器每次检测到策略违规都会发送 JSON 格式的报告。首先使用 Content-Security-Policy-Report-Only 头仅收集报告,确认不会破坏现有功能后再迁移到生产环境应用,这才是安全的导入步骤。
CSP 导入流程
导入时的常见失误
因为内联脚本无法运行就添加 'unsafe-inline',会使 CSP 的 XSS 防御效果几乎失效。迁移到 nonce 方式才是正解。
在 script-src 中指定 * 会导致可从任意域名加载脚本。应逐个列举允许的域名。
若忘记广告、分析、聊天小部件等第三方脚本,会导致生产环境中功能停止。
CSP 是与WAF和SSL/TLS并列的 Web 安全基础技术。Web 安全相关书籍 (Amazon)推荐据此进行系统性学习。也请一并参阅浏览器扩展的安全性、浏览器密码的安全性以及初创公司安全检查清单。
这篇文章对您有帮助吗?