最近Google又推出了两款有关CSP利用的小工具,其一为CSP Evaluator,这是一个可以评估你当前输入的CSP可否帮助你有效避免XSS攻击的工具,其用法很是简单,在输入框中输入你当前设置或将要设置的CSP值,选择须要验证的CSP版本,而后按下“CHECK CSP”便可。不知道CSP是什么的同窗,能够看下阿里聚安全博客之前推送的一篇文章《Content Security Policy 入门教程》javascript
下面的列表中会给出评估工具对你输入CSP的安全性评估,全部条目用不一样颜色标记了可能的影响程度。而且每一个条目均可以单击展开详情,以按照建议修复可能存在的缺陷。如图:html
CSP Evaluator还存在一个Chrome插件版本,一样易于使用。在使用了CSP的网站上单击扩展图标就能够自动对当前页面的CSP进行评估。java
另外一款工具为CSP Mitigator,这款Chrome插件容许您将自定义CSP策略应用于应用程序。 它能够帮助您了解启用CSP的后果,识别与您的策略不兼容的应用程序部分,并指导您在部署前进行任何须要的更改。效果图在Chrome商店中有,这里就再也不赘述了。web
能够看到,Google仍然在竭尽全力地推行CSP的发展与应用。在CSP Evaluator的页面中,咱们看到Google相关团队进行了一项规模巨大的研究来对CSP的现状进行了深刻的分析,并基于这些结果,剖析了CSP的优缺点,并对CSP将来的发展给出告终论。就让咱们跟随这篇文章,来看看CSP在今世的表现与CSP的将来是否能够期待。chrome
为了研究CSP(Content Security Policy)对XSS攻击的防御做用,他们作了对CSP安全模型的首次深刻分析,分析了CSP标准中对web缺陷的保护能力,帮助识别常见的CSP策略配置的可能错误,而且展现了三类能使CSP无效化的绕过方法。编程
此次研究所采用的材料基于从Google搜索的索引文件中所提取到的CSP策略,从语料库中提取了大约1060亿页的页面,其中39亿是受CSP保护的,其中确认了26,011个独立的策略。他们发现,因为策略配置错误和白名单条目不安全,这些策略中至少有94.72%没法缓解XSS攻击。基于这样的研究结果,他们建议在实践中部署CSP时,使用基于nonce的方法而不是传统的白名单。而且,他们提出了名为“strict dynamic”的新特性,这是当前在Chromium浏览器中实现的CSP3规范的一个新特性。如下会详细讲述为什么要使用这种策略和特性。浏览器
首先,何为CSP?咱们知道,内容安全策略(CSP)是一种声明机制,容许Web开发者在其应用程序上指定多个安全限制,由支持的用户代理(浏览器)来负责强制执行。CSP旨在“做为开发人员可使用的工具,以各类方式保护其应用程序,减轻内容注入漏洞的风险和减小它们的应用程序执行的特权”。当前,CSP还处在快速的发展期,目前正在进行规范中的版本是CSP3,CSP标准由用户代理选择实现。例如,Chromium具备完整的CSP2支持,而且实现了CSP3的大部分工做草案,仅在某些状况下可能会落后于实验中的某些特性,而Mozilla Firefox和基于WebKit的浏览器则刚刚得到了完整的CSP2支持。在实际使用中,CSP策略在Content-Security-Policy HTTP响应头或 元素中提供。安全
1.资源加载限制。 CSP的最广为人知和经常使用的方面是将各类子资源的加载限制到开发人员容许的一组源的能力,这组源称为源列表。 经常使用的指令是script-src,style-src,img-src和兜底的 default-src; 调节资源的指令的完整列表以下表1所示。做为特殊状况,script-src和style-src指令还有几个额外的配置选项可用; 这些选项容许对脚本和样式表进行更细粒度的控制。markdown
2.基于URL的限制。 某些类型的攻击不能经过管理子资源来防止,但与之相似,对于文档也须要有能够与之交互的可信来源的概念。 一个常见的例子是frame ancestors指令,它定义了容许的框架来源,以防止点击劫持。 相似地,base-uri和form-action定义哪些URL能够是<base#href>和<form#action>元素的目标,以防止一些Post XSS攻击。app
3.杂项限制和强化选项。因为在Web应用程序中缺少可以启用安全限制的其余常见机制,CSP已经成为几个松散适用的安全功能的集合。 这些功能包括block-all-mixed-content和upgrade-insecurerequests,它们能够防止HTTPS混合内容错误并帮助改进HTTPS支持; plugin-types可以限制容许的插件格式; 还有sandbox,它反映了HTML5沙箱框架的安全功能。
经过这些能力咱们能够看出,目前的CSP提供了对三种类型漏洞的保护功能:
XSS:XSS攻击能在一个脆弱的应用程序中注入并执行不受信任的脚本(用script-src和object-src指令来进行保护)
Clickjacking:Clickjacking经过在攻击者控制的页面上覆盖隐藏的框架来迫使用户在受影响的应用程序中执行不想要的操做。(经过限制框架嵌入和 frame-ancestors指令来保护)
Mixed content:Mixed content意味着在经过用HTTPS传递的页面上使用不安全协议加载资源(使用upgrade-insecure-requests和blockall-mixed-content关键字进行保护,限制将脚本和敏感资源加载到https网页中)
在谈论CSP带来的好处以前,咱们须要注意到。因为一些比较受欢迎的用户代理(浏览器)还不支持或者仅对CSP提供部分支持,因此若是应用仅仅依赖CSP做为深度防护的手段会很容易让安全机制彻底失败。所以,在使用CSP以外还必须采用传统保护机制; 例如,在生成HTML代码时使用带有严格上下文转义的框架,使用X-Frame-Options Header以防止点击劫持,并确保资源在安全页面上经过HTTPS协议获取。请务必记住,设置CSP的实际好处是,当主要的安全机制不够用时,CSP能够在开发人员引入编程错误时保护用户远离可能致使的XSS,点击劫持或者混合内容错误。
事实上,因为点击劫持能够经过X-Frame-Options来避免,而混合内容错误在现代浏览器中已经默认被阻止了。所以CSP做为标准被提出的最主要目的,就是用于防御XSS攻击。而XSS,也正是既能经过CSP来缓解,又是开发者常常容易引入应用的错误。在实现用CSP防止没必要要的脚本执行时,咱们制定的策略必须知足三个要求:
1.策略必须同时定义script-src和object-src(或者使用default-src来补全),在缺乏任意一项时都可以被绕过:
2.script-src的源列表不能包含unsafe-inline关键词(除非使用nonce)或者容许data: URI,不然能够被绕过:
3.script-src和object-src源列表不能包含含有攻击者可控制response的安全相关部分的源地址,或包含不安全的库。不然能够被绕过:
若是以上任意一条没有被知足的话,整个CSP对于XSS的防御就会完全失效。
因为CSP的基本假设之一就是在策略白名单中的域名只会提供安全的内容,所以从理论上来讲攻击者不该该可以将有效的JavaScript注入到白名单里来源的响应中。然而在实践中,咱们发现现代web应用程序每每会由于几种模式违反这个假设。
1.JavaScript带有用户可控的回调:某些JSONP函数接受用户传递的函数名,但未作严格的过滤,致使能够注入任意JavaScript代码执行,即便作了基本的过滤,也可能使用SOME攻击来注入任意函数名:
2.反射或者符号执行:CSP对于脚本执行的限制可能(一般是意外地)被白名单中的脚本所规避。 例如,脚本可使用反射来查找和调用全局做用域中的函数,如图:
一般状况下这些函数不会有太大危害,由于参数是开发人员所控制的。然而当函数从DOM获取数据,而应用又有DOM注入的漏洞,则极可能被攻击者彻底控制函数及其参数。一个典型的例子是目前流行的AngularJS库,它具备强大的模板语法和客户端模板执行:
默认状况下AngularJS会经过eval来执行代码,在特定的不容许eval的CSP场景下,AngularJS也支持使用“CSP compatibility mode” (ng-csp)来执行模板的代码。攻击者只须要从白名单中的域名里引入AngularJS,就能够在页面上经过注入ng-app标签来编写可以执行任意JavaScript代码的模板。
3.意料以外的可被当作的JavaScript来解析的响应:经过浏览器对MIME的检查宽松来执行任意js,好比伪造脚本响应类型。若是被黑客控制响应的话,在白名单中script-src和object-src均可能存在隐患。
4.做为安全手段的路径限制:CSP2中的whitelist能够指定路径(目录),然而若是白名单中的条目包含30X重定向,且能被黑客控制,则能够绕过CSP。
最多见于OAuth中,或被用于防止referer丢失。
为了找出互联网中有多少CSP策略可以切实有效地防御XSS攻击,Google团队构造了一些数据集并进行了标准化处理。根据咱们以上的结论,想要达到好的XSS防御效果,CSP的XSS保护策略必须处在强制模式下,而且至少包含如下两个指令之一:script-src或default-src。所以能够据此肯定含有XSS防御的CSP策略。对于策略的安全性检查,他们采用了以下几种方式检验:
1.对于“unsafe-inline”的使用:对于一个使用了“unsafe-inline”而且没有使用nonce的策略,能够认为是很容易被绕过的。
2.缺乏“object-src”:一个指定了“script-src”策略可是没有指定“object-src”(同时也没有“default-src”)的策略,是很容易用plugin绕过的。
3.在白名单中使用通配符:在白名单中使用通配符,或者使用URI Scheme很容易引发包含任意域名内容。
4.白名单中包含不安全的来源:若是白名单中的来源可能存在CSP Bypass,则也是不安全的。
对于如何检查存在CSP bypass的域名,咱们定义为:
1.托管了AngularJS的域名,由于AngularJS容许在模板中执行任意代码。
2.暴露了JSONP接口的域名(可使用JSONP任意定义js代码,或者SOME攻击自定义函数名)。
在进行了一系列数据的处理和分析以后,他们获得的结论是。在数据集中,有3,913,578,446(3.7%)个网址采用了CSP。 全部主机名中的1,664,019(0.16%)采用了CSP。他们将整个数据集分为3类:
1.全部策略
2.XSS-Protection 策略(至少含有script-src,object-src或者default-src之一)
3.严格XSS-Protection 策略(在2的基础上,不含unsafe-inline,unsafe-eval等,且URI Scheme,或者白名单通配符)
在此基础上,获得了目前互联网上CSP安全的总览:
1.全部策略数据中的94.72%并无提供XSS防御
2.在全部提供XSS防御的数据中,有94.68%能够被绕过
3.在全部提供XSS防御的数据中,有87.3%指定了unsafe-inline而且没有部署nonce
4.在全部提供XSS防御的数据中,有9.4%既没有指定object-src,也没有default-src
5.在全部提供XSS防御的数据中,有21.48%使用了通配符或者URI Scheme
6.在忽略3,5的状况下,仍有51.05%的能够被绕过。有些是由于4,更多的是由于script-src中的白名单中包含了不安全的域
经过对于所获得的对XSS有效的CSP防御策略的分析,咱们获得了白名单的安全性以下:
1.白名单数量越大,越难保证JSONP和AngularJS形成的安全问题
2.大概在严格策略中的41.65%,全部XSS防御策略中的79.17%,包含不安全的白名单
3.在使用12条白名单时,绕过率达到了94.8%
4.做为结果,咱们得出的结论是,部署传统的基于白名单的CSP模型中防止XSS是不可行的,由于在实践中脚本执行限制一般能够被推翻。
能够看出,script-src的白名单是形成CSP失效的最大缘由(除了没配置好的unsafe-inline和缺乏object-src以外)。所以,咱们应该如何改进CSP呢。其实CSP已经提供了更精细的方法来对信任脚本:加密随机数(cryptographic nonce)和哈希(hash)。 特别是nonces容许开发人员明确地注解每一个受信任的脚本(不论内联和外部),同时禁止攻击者注入的脚本执行。 为了提升CSP的总体安全性,Google据此提出了一种稍微不一样的策略写法。 应用程序维护者应该应用基于nonce的保护方法,而不是依赖白名单。 如下列表描述了基于白名单的CSP策略和知足此策略的脚本:
能够看出,白名单中包含了一个不安全的域名,所以所述CSP的策略就是不安全的。攻击者能够经过JSONP暴露出的点来注入恶意代码: https://example.org/script?callback=malicious_code.
为了防止这种事情的发生,咱们使用nonce来定义策略。在nonce中,应用程序定义并生成了单一的,不可猜想的令牌(nonce),这个令牌会同时传递给CSP策略和做为一个合法HTML属性传递给script。 用户代理仅容许执行那些nonce值可以匹配策略中指定的值的脚本。虽然攻击者能够将标记注入易受攻击的页面,可是因为不知道nonce的临时值,所以他并不能执行恶意脚本。
经过使用nonce,能够单独将脚本列入白名单。 即便攻击者可以定位XSS,nonce的值也是不可预测的,所以攻击者不可能向JSONP注入有效脚本。并且因为浏览器支持多个策略,所以能够把nonce和whitelist一块儿写,用逗号隔开。nonce能够用来将各个脚本列入白名单,而whitelist能够用于集中实施安全策略。
那么,当咱们生成动态脚本并插入时会发生什么呢?由于新生成的,被插入到页面的js并不知道nonce的值,因此会被拦截,所以须要CSP3里的 script-src: ’strict-dynamic’。’ trict-dynamic’容许将信任关系传递给动态生成的脚本,也就是说,“strict-dynamic”容许js动态添加的脚本执行,而忽略script-src的白名单。而且,其余的script-src白名单会被忽略,浏览器不会执行静态或解析器插入的脚本,除非它伴随有效的nonce值。这里的关键点是,使用createElement()来插入js时,可以执行createElement()的js已经被信任了,而且黑客不知道nonce的时候没法注入恶意脚本。所以咱们能够信任新建的js代码。举例,咱们能够这么写CSP: