CSP(Content Security Policy,内容安全策略) 是一种安全机制,用于防止包括 XSS(跨站脚本攻击)在内的多种类型的网络攻击。CSP 通过告诉浏览器只允许特定的资源(如脚本、样式、图片等)从可信任的源加载和执行,从而减少恶意脚本或资源的加载机会。
CSP 的基本原理
CSP 是通过 HTTP 头或 HTML 的 <meta>
标签来设置的,浏览器在加载页面时会根据 CSP 策略决定哪些资源是允许加载的,哪些是禁止的。如果页面中有违反策略的内容,浏览器会阻止这些内容的加载或执行,并在控制台显示错误信息。
常见的 CSP HTTP 头格式如下:
Content-Security-Policy: 指令1 参数1; 指令2 参数2; ...
CSP 核心功能和常见指令
1. default-src
default-src
是所有资源类型的默认源。如果没有为某种特定的资源类型指定单独的策略,它会继承 default-src
的设置。
示例:
Content-Security-Policy: default-src 'self'
这个策略表示默认情况下只允许加载来自同一域(self
)的资源,外部域的资源加载将被阻止。
2. script-src
script-src
用于控制 JavaScript 脚本的加载源,防止 XSS 攻击。
示例:
Content-Security-Policy: script-src 'self' https://trusted.com
这个策略表示允许从自身域和 https://trusted.com
加载 JavaScript 文件,其他源的脚本将被阻止。
特殊的 script-src
值:
'self'
:只允许从当前源加载资源。'none'
:不允许加载任何资源。'unsafe-inline'
:允许内联的 JavaScript(但可能引发安全问题,因此应尽量避免使用)。'unsafe-eval'
:允许使用eval()
和类似的动态代码执行函数(通常会引发安全风险,建议禁用)。
3. style-src
style-src
用于控制 CSS 样式表的加载源。
示例:
Content-Security-Policy: style-src 'self' https://trusted.com
这个策略表示允许从同一域和 https://trusted.com
加载样式表。
特殊的 style-src
值:
'unsafe-inline'
:允许内联的 CSS 样式(可能带来安全风险)。
4. img-src
img-src
控制图像的加载源。
示例:
Content-Security-Policy: img-src 'self' https://images.com
表示允许从当前域和 https://images.com
加载图片。
5. connect-src
connect-src
控制通过 XMLHttpRequest
、WebSocket
、fetch
等发起的网络请求。
示例:
Content-Security-Policy: connect-src 'self' https://api.trusted.com
只允许对自身域和 https://api.trusted.com
的连接请求,其他请求将被阻止。
6. font-src
font-src
控制字体文件的加载源。
示例:
Content-Security-Policy: font-src 'self' https://fonts.trusted.com
只允许从当前域和 https://fonts.trusted.com
加载字体。
7. frame-src
frame-src
控制 iframe
、frame
标签的嵌入内容源。
示例:
Content-Security-Policy: frame-src 'self' https://trusted.com
表示只允许从自身域和 https://trusted.com
嵌入框架内容。
8. object-src
object-src
用于控制加载 <object>
、<embed>
、<applet>
等标签的内容源。
示例:
Content-Security-Policy: object-src 'none'
禁止加载任何对象标签的内容,这可以防止基于插件的攻击,如 Flash 攻击。
9. form-action
form-action
限制哪些 URL 可以作为表单提交的目标,防止表单劫持。
示例:
Content-Security-Policy: form-action 'self'
只允许将表单提交到同一域,其他域将被阻止。
10. frame-ancestors
frame-ancestors
指定哪些源可以嵌入当前页面,防止点击劫持(Clickjacking)攻击。
示例:
Content-Security-Policy: frame-ancestors 'self'
表示只允许当前页面被自身域的 iframe
嵌入。
CSP 示例
一个常见的 CSP 设置可能如下:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' https://api.trusted.com
这个策略的含义是:
- 默认情况下,只允许从同一域加载资源。
- 允许 JavaScript 脚本从同一域和
https://trusted.com
加载。 - 允许样式表从同一域加载,且允许内联样式。
- 允许图片从同一域加载,并允许使用
data:
URI 的图片。 - 允许通过
XMLHttpRequest
、WebSocket
等进行网络请求,目标可以是同一域和https://api.trusted.com
。
CSP 报告机制
CSP 还支持设置一个报告 URI 来收集违反策略的事件。例如:
Content-Security-Policy: default-src 'self'; report-uri /csp-report
当浏览器检测到违反 CSP 策略的行为时,它会将事件报告发送到指定的 URI。你可以通过这些报告监控潜在的安全问题并调整策略。
CSP 的限制和注意事项
- 复杂性:CSP 的配置可能较为复杂,尤其是当网站依赖多个第三方资源时,需要精确指定哪些外部资源是可信的。
unsafe-inline
和unsafe-eval
:尽量避免使用'unsafe-inline'
和'unsafe-eval'
,因为它们会允许内联脚本和动态代码执行,削弱 CSP 的防护能力。- 逐步部署:可以使用
Content-Security-Policy-Report-Only
头来逐步测试 CSP 策略,而不会阻止资源加载。这样可以收集报告,了解哪些资源违反了策略,并逐步调整 CSP 设置。
通过合理的 CSP 配置,可以有效防止 XSS 攻击和其他类型的内容注入攻击,极大地提高 Web 应用的安全性。