内容安全策略(Content Security Policy),简称 CSP,顾名思义了,是一种针对内容安全方面的保护策略。作用是用来定义页面中哪些资源可以加载,以减少 XSS 的发生
。
Chrome 25+ 和 Firefox 23+ 已经加入对 CSP 的支持,其它浏览器的支持起步较晚,不过现在的浏览器已经较普遍的支持了。浏览器的具体支持情况可以参看 CanIUse。
什么是 XSS 攻击
跨站脚本(英语:Cross-site scripting,通常简称为:XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了 HTML 以及用户端脚本语言。
跨域脚本攻击(XSS 攻击)通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是 JavaScript,但实际上也可以包括 Java,VBScript,ActiveX,Flash 甚至是普通的 HTML。攻击成功后,攻击者可能得到更高的权限(如执行一些操作)、私密网页、会话和 cookie 等各种内容。
为了防止它,要采取很多编程对策,成本较高。很多人发出呼声,能不能让浏览器自己禁止外部注入恶意脚本
呢?这时,CSP 应运而生。
什么是 CSP
上文已提到,CSP 定义了页面中哪些资源可以加载。
所以 CSP 的实质就是白名单
,Web 端明确地告诉客户端,只有哪些外部资源可以加载可以执行,相当于提供一份白名单,“我的规则里没提到的全部拜拜,不给进来”。
因此 CSP 大大增强了网页的安全性。即使攻击者发现可趁之机,也没法注入脚本。
CSP 的两种启用方式
两种方法启用 CSP :
一种是使用网页的 <meta>
标签
<meta http-equiv="Content-Security-Policy" content="default-src ${value}; script-src ${value}; style-src ${value}; img-src ${value}; font-src ${value}; media-src ${value}; object-src ${value}; connect-src ${value}; child-src ${value}; sandbox ${value}; report-uri ${value}">
一种是使用 HTTP 响应头
Content-Security-Policy: "default-src ${value}; script-src ${value}; style-src ${value}; img-src ${value}; font-src ${value}; media-src ${value}; object-src ${value}; connect-src ${value}; child-src ${value}; sandbox ${value}; report-uri ${value}"
以上,例如 script-src
是 参数项
,${value}
是 参数值
。作为白名单的 CSP 机制,参数项都是可选项
。
CSP 的规则定义
一、参数项
的定义见下表:
参数项 | 定义 |
---|---|
default-src | 所有类型资源的默认加载策略。若某类型资源有独立定义加载策略就跟随该独立定义;反之跟随 default-src 的定义值 |
script-src | JavaScript 的加载策略 |
style-src | 样式的加载策略 |
img-src | 图片的加载策略 |
font-src | WebFont 的加载策略 |
media-src | <audio> <video> 等标签引入的 HTML 多媒体的加载策略 |
object-src | <object> <embed> <applet> 等标签引入的 flash 等插件的加载策略 |
connect-src | Ajax、WebSocket 等请求的加载策略。若策略的值为不允许,浏览器会模拟一个状态 400 的响应 |
child-src | frame 的加载策略 |
sandbox | 对请求的资源启用 sandbox。参数值可参考 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox |
report-uri | 告诉浏览器,若请求的资源不被 CSP 策略允许时,往哪个地址提交日志信息 |
二、参数值
的定义见下表:
参数值 | 定义 |
---|---|
(空) | 允许任何内容 |
‘none’ | 不允许任何内容 |
‘self’ | 允许来自相同来源(相同的域名、端口、协议)的内容 |
example.org | 允许加载指定域名的资源 |
*.example.org | 允许加载 example.org 任何子域名的资源 |
https://example.org | 允许加载指定域名的 HTTPS 协议的资源 |
https: | 允许加载 HTTPS 资源 |
data: | 允许 data: 协议 |
‘unsafe-inline’ | 仅用于 script-src 和 style-src 的值。允许加载 inline 资源(例如常见的 onclick、inline js、style 属性、inline css 等 |
‘unsafe-eval’ | 仅用于 script-src 的值。允许加载动态 js 代码,例如 eval、setTimeout、new Function 等 |
以上,CSP 可控制的项目非常丰富。
如果不指定 ‘unsafe-inline’ ,页面上所有 inline 样式都不会执行;不指定 ‘unsafe-eval’,页面上所有 eval 等动态代码都不会执行。
在限制页面资源加载后,被 XSS 的可能性小了不少。
当然,仅仅靠 CSP 来防范 XSS 显然远远不够。但它成本低,用起来方便啊。
CSP 在 Nginx 中的启用
上文已提到,CSP 可通过 HTTP 响应头
的方式部署。
若要在 Nginx 中配置:
add_header Content-Security-Policy "default-src ${value}; script-src ${value}; style-src ${value}; img-src ${value}; font-src ${value}; media-src ${value}; object-src ${value}; connect-src ${value}; child-src ${value}; sandbox ${value}; report-uri ${value}";
举个例子,本站的 CSP 是这样的:
add_header Content-Security-Policy "default-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://www.w3.org https://avatars0.githubusercontent.com; font-src 'none'; media-src 'none'; object-src 'none'; connect-src 'self' https://github.com https://api.github.com; child-src 'none'" always;
现代 web 浏览器已提供许多安全性响应头支持,更多详细可阅读我的另一篇帖子 那些站点安全相关的 HTTP 响应头
转载请注明:逗比根据地 » Content Security Policy 概述