在互联网中,网页的面临安全性问题很多,虽然HTTPS能解决大多数的问题,但HTTPS在国内环境中存在严重的劫持问题,所以在某些网络情况下还在使用HTTP协议,也就面临着:

  1. JS劫持;
  2. 广告注入;
  3. 跨站脚本攻击(XSS);

等等诸多问题。

CSP简介

Content Security Policy简称CSP,用来解决跨站脚本攻击及其类似安全问题的一组安全策略,可用来初步解决上面的问题。

CSP发展很快,自2012年第一版诞生依赖,至今第二版已经进入W3C的推荐版本,第三版也处于工作草案阶段。W3C建议浏览器基于第二版规范实现(浏览器兼容性),CSP在第二版中的官方定义如下:

This document defines a policy language used to declare a set of content restrictions for a web resource, and a mechanism for transmitting the policy from a server to a client where the policy is enforced.

CSP中指令名的含义

指令名 规范版本 含义
default-src Level 1 加载JavaScript、CSS、图片、字体、AJAX、Frame和HTML5媒体等资源的默认策略
script-src Level 1 定义合法的JavaScript源
style-src Level 1 定义合法的CSS样式表源
img-src Level 1 定义合法的图片源
font-src Level 1 定义合法的字体源
connect-src Level 1 适用于XMLHttpRequest (AJAX), WebSocket或EventSource。当不合法的请求发出时,浏览器会模拟一个404回复
media-src Level 1 定义合法的媒体源,例如HTML5中的<audio><video>元素
object-src Level 1 定义合法的插件源,例如<object><embed&gt<applet>
frame-src Deprecated 定义合法的框架源。使用child-src替代其更合适
sandbox Level 1 针对请求的资源使用沙箱,类似于iframesandbox属性。沙箱适用于同源策略,禁用弹窗,被阻止的插件和脚本。保持空属性值以保留所有限制,也可以添加后面的值:allow-forms allow-same-origin allow-scripts allow-popupsallow-modalsallow-orientation-lockallow-pointer-lockallow-presentationallow-popups-to-escape-sandbox,和allow-top-navigation
report-uri Level 1 指定策略应用失败的URI,也可以在Content-Security-PolicyHTTP头后添加-Report-Only指示浏览器仅报告错误,但不阻止内容的加载
child-src Level 2 定义web worker或者frame的合法源,例如<frame><iframe>
form-action Level 2 定义<form>action属性使用的合法源
frame-ancestors Level 2 定义<frame> <iframe> <object> <embed> <applet>等元素使用的合法源。将其设置为none大致等于X-Frame-Options: DENY
plugin-types Level 2 定义通过<object>和<embed>元素调用的资源类型。例如加载<applet>需要设置application/x-java-applet

CSP中指令值的含义

上述的任何CSP指令均可以赋一下值,有效值类型的列表如下:

指令值 示例 含义
* img-src * 通配符,允许任何URL接收data: blob: filesystem: schemes
‘none’ object-src 'none' 拒绝加载任何资源
‘self’ script-src 'self' 允许加载同源资源(相同的协议、域名、端口)
data: img-src 'self' data: 允许加载data编码的资源(例如图片的Base64编码)
domain.example.com img-src domain.example.com 允许从指定的域名加载资源
*.example.com img-src *.example.com 允许从example.com下的任何子域名加载资源
https://cdn.com img-src https://cdn.com 允许加载https://cdn.com下的资源
https: img-src https: 仅允许加载https协议的资源
‘unsafe-inline’ script-src 'unsafe-inline' 允许使用内联元素,比如style属性,onclick,或script标签
‘unsafe-eval’ script-src 'unsafe-eval' 允许不安全的动态脚本执行,比如JavaScript的eval()

使用方式

CSP主要有两种使用方式HTTP HEADER和标签两种方式:

// header
Content-Security-Policy: default-src https:
// meta tag
<meta http-equiv="Content-Security-Policy" content="default-src https:">

案例分析

页面在最终用户面前显示时,页面内容可能在中间的任何一个网络环节被篡改或者拦截,因此网页中的各种资源类型都需要做一定的约束。需要约束的主要资源列表如下:

  1. JS文件,JS文件是浏览器中最具有表现力的文件,可以修改浏览器中渲染页面的任何元素;
  2. CSS文件,CSS文件决定了浏览器外观,CSS文件的篡改可以让浏览器中的渲染的页面样子完全改变;
  3. HTML文件,HTML文件可能被追加内容(最常见),当然也可以删改,甚至可能完全拦截;
  4. iframe元素,iframe元素类似HTML页面中的一个沙盒,像是一个独立的世界,所以要对iframe元素的内容呈现进行约束;
  5. 等等

同时行内脚本的解析要暂时放开。

根据以上条件,最后的策略值如下:

// 使用时需要去掉换行和注释
Content-Security-Policy:
    // 默认情况,严格安全策略
    default-src 'none'; 
    // 限制jsonp,外联脚本,内联脚本和行内事件绑定,以及可能的eval
    script-src *.domain.com *.domainimg.com 'unsafe-inline' 'unsafe-eval'; 
    // 限制外联样式和内联样式
    style-src *.domainimg.com 'unsafe-inline'; 
    // ajax限制同源限制
    connect-src 'self'; 
    // 限制图片,支持HTTP和HTTPS,如备注解释
    img-src http://*.domainimg.com https://*.domainimg.com; 
    // 限制字体文件
    font-src *.domain.com *.domainimg.com; 
    // 限制iframe,这行代码虽然标注废弃,但在旧版本浏览器中适用
    frame-src none; 
    // 限制iframe
    child-src: none; 
    // 限制iframe
    frame-ancestors: none;

注意

注意在HTTPS页面中启用CSP之后,会禁用HTTP的请求,类似添加了block-all-mixed-content指令的效果,而且block-all-mixed-content不能关闭,解决这个问题的方法可以是: 在需要http的资源类型中,如上img-src中明确写明http和https两种模式。

参考

  1. Content Security Policy
  2. 浏览器支持情况
  3. Content Security Policy Level 2 介绍
  4. Content Security Policy 介绍