HTML5安全介绍之内容安全策略(CSP)简介_html5教程技巧
2020-11-27
来源:乌哈旅游
万维网的安全策略植根于同源策略。例如www.gxlcms.com的代码只能访问www.gxlcms.com的数据,而没有访问http://www.baidu.com的权限。每个来源都与网络的其它部分分隔开,为开发人员构建了一个安全的沙箱。理论上这是完美的,但是现在攻击者已经找到了聪明的方式来破坏这个系统。
这就是XSS跨站脚本攻击,通过虚假内容和诱骗点击来绕过同源策略。这是一个很大的问题,如果攻击者成功注入代码,有相当多的用户数据会被泄漏。
现在我们介绍一个全新的、有效的安全防御策略来减轻这种风险,这就是内容安全策略(ContentSecurity Policy,CSP)。
来源白名单
XSS攻击的核心是利用了浏览器无法区分脚本是被第三方注入的,还是真的是你应用程序的一部分。例如Google +1按钮会从https://apis.google.com/js/plusone.js加载并执行代码,但是我们不能指望从浏览器上的图片就能判断出代码是真的来自apis.google.com,还是来自apis.evil.example.com。浏览器下载并执行任意代码的页面请求,而不论其来源。
CSP定义了Content-Security-PolicyHTTP头来允许你创建一个可信来源的白名单,使得浏览器只执行和渲染来自这些来源的资源,而不是盲目信任服务器提供的所有内容。即使攻击者可以找到漏洞来注入脚本,但是因为来源不包含在白名单里,因此将不会被执行。
以上面Google +1按钮为例,因为我们相信apis.google.com提供有效的代码,以及我们自己,所以可以定义一个策略,允许浏览器只会执行下面两个来源之一的脚本。
Content-Security-Policy:script-src 'self' https://apis.google.com
是不是很简单?script-src可以为指定页面控制脚本相关权限。这样浏览器只会下载和执行来自http://apis.google.com和本页自身的脚本。
一旦我们定义了这个策略,浏览器会在检测到注入代码时抛出一个错误(请注意是什么浏览器)。
内容安全策略适用于所有常用资源
虽然脚本资源是最明显的安全隐患,但是CSP还提供了一套丰富的指令集,允许页面控制加载各种类型的资源,例如如下的类型:
content-src:限制连接的类型(例如XHR、WebSockets和EventSource)
font-src:控制网络字体的来源。例如可以通过font-src https://themes.googleusercontent.com来使用Google的网络字体。
frame-src:列出了可以嵌入的frame的来源。例如frame-src https://youtube.com只允许嵌入YouTube的视频。
img-src:定义了可加载图像的来源。
media-src:限制视频和音频的来源。
object-src:限制Flash和其他插件的来源。
style-src:类似于Script-src,只是作用于css文件。
默认情况下,所有的设置都是打开的,不做任何限制。你可以以分号分隔多个指令,但是类似于script-src https://host1.com;script-src https://host2.com的形式,第二个指令将会被忽略。正确的写法是script-src https://host1.com https://host2.com。
例如,你有一个应用需要从内容分发网络(CDN,例如https://cdn.example.net)加载所有的资源,并且知道不需要任何frame和插件的内容,你的策略可能会像下面这样:
Content-Security-Policy:default-src https://cdn.example.net; frame-src 'none'; object-src 'none'
细节
我在例子里使用的HTTP头是Content-Security-Policy,但是现代浏览器已经通过前缀来提供了支持:Firefox使用x-Content-Security-Policy,WebKit使用X-WebKit-CSP。未来会逐步过渡到统一的标准。
策略可以根据每个不同的页面而设定,这提供了很大的灵活度。因为你的站点可能有的页面有Google +1的按钮,而有的则没有。
每个指令的来源列表可以相当灵活,你可以指定模式(data:, https:),或者指定主机名在一个范围(example.com,它匹配主机上的任意来源、任意模式和任意端口),或者指定一个完整的URI(https://example.com:443,特指https协议,example.com域名,443端口)。
你在来源列表中还可以使用四个关键字:
“none”:你可能期望不匹配任何内容
“self”:与当前来源相同,但不包含子域
“unsafe-inline”:允许内联Javascript和CSS
“unsafe-eval”:允许文本到JS的机制例如eval
请注意,这些关键词需要加引号。
沙箱
这里还有另外一个值得讨论的指令:sandbox。和其他指令有些不一致,它主要是控制页面上采取的行为,而不是页面能够加载的资源。如果设置了这个属性,页面就表现为一个设置了sandbox属性的frame一样。这对页面有很大范围的影响,例如防止表单提交等。这有点超出了本文的范围,但是你可以在HTML5规范的“沙箱标志设置”章节找到更多信息。
有害的内联代码
CSP基于来源白名单,但是它不能解决XSS攻击的最大来源:内联脚本注入。如果攻击者可以注入包含有害代码的script标签(
显示全文