CSP简介和案例分析
在互联网中,网页的面临安全性问题很多,虽然HTTPS能解决大多数的问题,但HTTPS在国内环境中存在严重的劫持问题,所以在某些网络情况下还在使用HTTP协议,也就面临着:
- JS劫持;
- 广告注入;
- 跨站脚本攻击(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> 或<applet> |
frame-src | Deprecated | 定义合法的框架源。使用child-src 替代其更合适 |
sandbox | Level 1 | 针对请求的资源使用沙箱,类似于iframe 的sandbox 属性。沙箱适用于同源策略,禁用弹窗,被阻止的插件和脚本。保持空属性值以保留所有限制,也可以添加后面的值:allow-forms allow-same-origin allow-scripts allow-popups ,allow-modals ,allow-orientation-lock ,allow-pointer-lock ,allow-presentation ,allow-popups-to-escape-sandbox ,和allow-top-navigation |
report-uri | Level 1 | 指定策略应用失败的URI,也可以在Content-Security-Policy HTTP头后添加-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:">
案例分析
页面在最终用户面前显示时,页面内容可能在中间的任何一个网络环节被篡改或者拦截,因此网页中的各种资源类型都需要做一定的约束。需要约束的主要资源列表如下:
- JS文件,JS文件是浏览器中最具有表现力的文件,可以修改浏览器中渲染页面的任何元素;
- CSS文件,CSS文件决定了浏览器外观,CSS文件的篡改可以让浏览器中的渲染的页面样子完全改变;
- HTML文件,HTML文件可能被追加内容(最常见),当然也可以删改,甚至可能完全拦截;
- iframe元素,iframe元素类似HTML页面中的一个沙盒,像是一个独立的世界,所以要对iframe元素的内容呈现进行约束;
- 等等
同时行内脚本的解析要暂时放开。
根据以上条件,最后的策略值如下:
// 使用时需要去掉换行和注释
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两种模式。