日期:2014-05-17  浏览次数:20758 次

HTML5安全:内容安全策略(CSP)简介

        前言:HTML5出现后,网络安全更加受到广泛的关注。Web对于网络安全有哪些改进?我们如何来面对越来越危险的网络欺诈和攻击?下面的文章谈到了W3C对于这个问题的最新解决方案。未来有机会的话,我会针对XSS、P3P、同源策略、CORS(跨域资源共享)和CSP进行关于HTML5内容安全的现场分享。

        ------------------------华丽的分界线

        注意:本文所讨论的API还未最终确定,请在自己的项目中谨慎使用。

        万维网的安全策略植根于同源策略。例如http://blog.csdn.net/hfahe的代码只能访问http://blog.csdn.net的数据,而没有访问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

        请注意,这些关键词需要加引号。

沙箱

&nbs