Content Security Policy(CSP)指令

本文介绍CSP的指令,基于CSP level 3,由于文档截止发文时未定稿,可能出现内容陈旧、错误等问题。

为了减缓跨站脚本攻击,网站开发者应该包含控制脚本和插件资源的指令。他们可以这样做:

  • 包含script-src和object-src指令或
  • 一个default-src指令

开发者不应在策略中包含’unsafe-inline’或data:指令。他们都会允许通过文档中直接包含的代码进行XSS攻击。因此最好彻底避免使用这两个指令。

child-src
child-src指令管理嵌套浏览上下文(iframe、frame)和Worker执行上下文。
示例:
Content-Security-Policy: child-src https://example.com/
下面的代码会引发网络错误,因为url不匹配给出的url模式:

<iframe src="https://not-example.com"></iframe>
var blockedWorker = new Worker("data:application/javascript,...");

connect-src
connect-src指令限制从脚本接口加载的url。
通过脚本接口加载资源的方式指:fetch、XHR、eventSource、Beacon、a标签的ping、WebSocket。
示例:
Content-Security-Policy: connect-src https://example.com/
下面代码会引发网络错误:

<a ping="https://not-example.com">...
  var xhr = new XMLHttpRequest();
  xhr.open('GET', 'https://not-example.com/');
  xhr.send();

  var ws = new WebSocket("https://not-example.com/");

  var es = new EventSource("https://not-example.com/");

  navigator.sendBeacon("https://not-example.com/", { ... });

default-src
default-src指令是在其他指令没有定义时的默认指令。
示例:

Content-Security-Policy: default-src 'self'
相当于下面的指令:
Content-Security-Policy: connect-src 'self';
                         font-src 'self';
                         frame-src 'self';
                         img-src 'self';
                         manifest-src 'self';
                         media-src 'self';
                         object-src 'self';
                         script-src 'self';
                         style-src 'self';
                         worker-src 'self'
以下指令:
Content-Security-Policy: default-src 'self'; script-src https://example.com
等价于:
Content-Security-Policy: connect-src 'self';
                         font-src 'self';
                         frame-src 'self';
                         img-src 'self';
                         manifest-src 'self';
                         media-src 'self';
                         object-src 'self';
                         script-src https://example.com;
                         style-src 'self';
                         worker-src 'self'

font-src
font-src指令限制字体文件资源加载的URL。
示例:
Content-Security-Policy: font-src https://example.com/
下面的代码会触发网络错误:

@font-face {
    font-family: "Example Font";
    src: url("https://not-example.com/font");
  }
  body {
    font-family: "Example Font";
  }

frame-src
frame-src指令限制嵌套浏览上下文加载的URL。
示例:
Content-Security-Policy: frame-src https://example.com/
下面的代码会触发网络错误:

<iframe src="https://not-example.com/"></iframe>

img-src
img-src指令限制了图片资源加载的URL。
示例:
Content-Security-Policy: img-src https://example.com/
下面代码会触发网络错误:

<img src="https://not-example.com/img" />

manifest-src
manifest-src指令限制应用的manifests文件资源加载的URL。
示例:
Content-Security-Policy: manifest-src https://example.com/
下面代码会触发网络错误:

<link rel="manifest" href="https://not-example.com/manifest">

media-src
media-src指令限制了音频、视频、相关文本追踪的URL。
示例:
Content-Security-Policy: media-src https://example.com/
下面代码会触发网络错误:

<audio src="https://not-example.com/audio"></audio>
<video src="https://not-example.com/video">
    <track kind="subtitles" src="https://not-example.com/subtitles">
</video>

object-src
object-src指令限制插件内容加载的URL。
示例:
Content-Security-Policy: object-src https://example.com/
下面代码会触发网络错误:

<embed src="https://not-example.com/flash"></embed>
<object data="https://not-example.com/flash"></object>
<applet archive="https://not-example.com/flash"></applet>

如果插件的内容没有通过相关的URL(如object元素没有data属性,但是根据指定的类型加载了默认的插件),除非object-src的值是’none’必须阻止,否则都会允许。

script-src
script-src指令限制脚本执行的位置。这不仅包含直接通过script元素引用的URL还包括内联脚本块和XSLT样式表触发的脚本执行。

style-src
style-src指令限制样式应用的位置。包括link标签、@import、HTTP头加载的样式。

worker-src
worker-src指令限制Worker、SharedWorker或ServiceWorker加载的URL。
示例:
Content-Security-Policy: worker-src https://example.com/
下面代码会引发网络错误:

var blockedWorker = new Worker("data:application/javascript,...");
  blockedWorker = new SharedWorker("https://not-example.com/");
  navigator.serviceWorker.register('https://not-example.com/sw.js');

base-uri
base-uri指令限制base元素中的URL。

plugin-types
plugin-types指令限制可被加载的插件类型。
示例:
Content-Security-Policy: plugin-types application/pdf
下面代码会引发网络错误:

<!-- No 'type' declaration(没有声明type) -->
<object data="https://example.com/flash"></object>

<!-- Non-matching 'type' declaration(声明的type和允许的type不一致) -->
<object data="https://example.com/flash" type="application/x-shockwave-flash"></object>

<!-- Non-matching resource(虽然声明的type一致,但其实返回的资源还是个flash类型,也会报错) -->
<object data="https://example.com/flash" type="application/pdf"></object>

下面的策略:
Content-Security-Policy: plugin-types application/x-shockwave-flash
会成功加载如下资源:

<!-- Matching 'type' declaration and resource -->
<object data="https://example.com/flash" type="application/x-shockwave-flash"></object>

sandbox
sandbox指令指定一个客户端需要应用于资源的HTML沙箱策略,就如同包含于带sandbox属性的iframe标签中。

disown-opener
disown-opener指令确保资源与其opener断绝关系。

form-action
form-action指令限制form表单提交的URL。

frame-ancestors
frame-ancestors指令限制可以被通过frame、iframe、object、embed、applet元素嵌入的资源的URL。

report-uri
report-uri指令用于报告非法请求,已过时,应使用report-to指令代替。

report-to
report-to指令用于发送非法的请求信息。