内容安全策略

简介

内容安全策略(Content Security Policy)可以控制浏览器信任以何种方式、何种来源去加载资源,用于削弱 XSS 的危害,也可以防止使用 HTTP 时被注入恶意代码,通过服务器返回 Content-Security-Policy 来告诉浏览器具体的策略,因此需要浏览器支持。
另外 meta 元素也可以设置:

1
2
3
4
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; img-src https://*; child-src 'none';"
/>

这里可以看到,CSP 是通过规定可信域,来限制脚本或者其他静态资源的执行。

常见字段

字段之间通过分号相隔,字段值可以使用通配符,多个值以空格相隔。
self 代表本站

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 允许所有内容来源于本站及myt0.com子域名
default-src 'self' *.myt0.com

# 所有内容来源于myt0.com,并且要通过https协议,防止监听
default-src https://myt0.com

# 图片来源于所有
img-src *

# 样式来源设置
style-src myt0.com

# 限制音频地址
media-src myt0.com youtube.com

# 限制JS脚本地址,禁止行内脚本,禁止eval函数
script-src myt0.com 'unsafe-inline' 'unsafe-eval'

# 限制<object>, <embed>, <applet>标签的来源
object-src https://myt0.com

其他字段的解释及浏览器兼容具体参见MDN 内容安全策略( CSP )

报告模式

Content-Security-Policy-Report-Only 会启用报告模式,不强制采用指定的策略,但是违规的行为会报告给一个指定的 URI,也可以用这个头来进行测试。
Content-Security-Policy-Report-Only 和 Content-Security-Policy 同时存在时,两者均有效,前者仅报告,后者强制执行策略。
Content-Security-Policy 增加 report-uri 启用违规报告:

1
Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi

当违规行为发生时,会将违规结果以 POST 方式发送到指定 URI,格式为 JSON,语法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"csp-report": {
//发生违规的文档的URI
"document-uri": "http://example.com/signup.html",
//违规发生处的文档引用(地址)
"referrer": "",
//被CSP阻止的资源URI。如果被阻止的URI来自不同的源而非文档URI,那么被阻止的资源URI会被删减,仅保留协议,主机和端口号。
"blocked-uri": "http://example.com/css/style.css",
//违反的策略名称。
"violated-directive": "style-src cdn.example.com",
//在 Content-Security-Policy HTTP 头部中指明的原始策略
"original-policy": "default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports"
}
}

nginx 配置

在 conf 中加入:

1
add_header Content-Security-Policy "script-src 'self' 'unsafe-inline' 'unsafe-eval' *.youtube.com maps.gstatic.com *.googleapis.com *.google-analytics.com cdnjs.cloudflare.com assets.zendesk.com connect.facebook.net; frame-src 'self' *.youtube.com assets.zendesk.com *.facebook.com s-static.ak.facebook.com tautt.zendesk.com; object-src 'self'";