【编者的话】Dropbox的Web安全防护措施之一是使用基于内容的安全策略(CSP)。Dropbox的安全工程师Devdatta Akhawe通过四篇文章,介绍了CSP在Dropbox中推广的细节和经验。Dropbox的CSP原则大大减少了XSS和内容注入攻击。不过,大规模使用比较严苛的CSP规则将面临诸多挑战。我们希望通过这四篇CSP系列文章,将Dropbox在实践CSP过程中的收获分享给广大开发社区朋友。第一篇文章主要介绍如何在规则中设置报表筛选管线来标记错误;第二篇介绍Dropbox如何在上述规则中配置随机数及缓解 unsafe-inline
带来的安全风险;第三篇介绍如何降低 unsafe-eval
造成的风险,以及介绍Dropbox所开发的开源补丁;最后一篇介绍在权限分离机制下,如何减小第三方软件整合时的风险。本篇是该系列文章的第一篇,主要讨论CSP的报告和过滤机制。
Dropbox始终坚定地贯彻着 Content Security Policy (CSP)。如果读者对CSP规则还不熟悉,我们建议先阅读Mike West的《 Excellent Introduction to CSP 》。简单来说,CSP的核心是一种说明性的机制,它在网页应用中将可靠的内容源(脚本、对象、图像的源等)添加至白名单中。
使用CSP限制了内容源,从而降低了网页应用中注入攻击的风险。下面的例子展示了在对Dropbox主页发出请求时所使用的CSP中的 script-src
指令。
script-src https://www.google.com/recaptcha/api/ https://ajax.googleapis.com/ajax/libs/jquery/ https://cf.dropboxstatic.com/static/api/ https://cf.dropboxstatic.com/static/javascript/ https://cf.dropboxstatic.com/static/coffee/compiled/ https://www.dropboxstatic.com/static/javascript/ https://www.dropboxstatic.com/static/coffee/ 'unsafe-eval' 'self' 'unsafe-inline' 'nonce-w+NfAhVZiaXzHT1RmBqS'
指令列出了所有可信赖的URI(包括浏览器支持的完整路径),通过这些URI可以载入所需的脚本代码。当支持CSP的网页浏览器检测到了脚本标签,它接下来会检查src属性,并和 script-src
指令提供的白名单进行对照。如果脚本源不在白名单中(比如,HTML注入漏洞的原因),浏览器就会阻止请求。
现在,复杂的网页应用识别和执行CSP标头是一个比较困难的问题,不过有一个CSP允许的小技巧可以解决这个问题,这便是report-only模式。report-only模式的关键方法是,允许网页测试规则在给制定者选定的终端发送错误报告时的影响。比方说,可以设置一项内容为 script-src ‘none’
的report-only规则,用来获取所有脚本来源的位置。
report-only模式大大增强了CSP的可行性:首先在report-only模式下反复迭代设定的规则,直到没有错误报告,之后转换为执行模式。这一步骤往往是CSP进入执行模式前,建议实行的 第一步准备工作 。在笔者最近参加的一次 研讨会 中,安全机制专家组着重介绍了CSP的report-only模式如何可以有效地推广CSP的使用,它能够做到某一项规则在使用前就可以评估其效果。
为了获得对已实施规则的有效反馈信息,CSP的报告功能不可或缺。Dropbox在转换到CSP的“阻塞”模式前,曾经使用report-only模式长达数月。但在开始大规模使用CSP时,便遇到了第一个问题:报告中的噪声(sheer noise)会使得默认报告机制失效。
我们发现,最大的噪声源是浏览器扩展工具。扩展工具在网页中插入了脚本或其他程序可能修改了HTML,由于CSP会阻止网页上运行的所有未知内容,因此注入到网页中的内容很可能也会被浏览器阻止。如果我们仅仅把所有收到的报告加入日志中,那么日志也会包含以上错误。又因为我们无法控制扩展工具,所以也就没有办法做到报告中不添加扩展工具带来的错误信息。
经过一年的CSP大规模应用实践,Dropbox已经完成了一个精确调整的过滤机制,它可以忽略一般的误报。我们的报告管线筛选掉误报的报告内容,然后才将有效的报告加入分析处理后台。本着推广CSP的精神,Dropbox将这个过滤器技术分享出来,希望其他开发者可以使用。我们强烈建议读者阅读Neil Matatall这篇介绍 精准CSP列表的文章 ,实际上我们使用的列表也参考了文章中涉及的技术。
初看起来,筛选错误报告似乎有些奇怪,为什么不想知道广告插入和网页垃圾什么时候修改了网页应用呢?但是在这里,我们讨论的是CSP的预使用阶段,主要关注点是CSP的内容白名单不会使网页应用崩溃。滤除报告中的噪声,保证了CSP执行时对网页应用进行合理的修改。一旦转换到CSP执行模式,浏览器将根据过滤后的报告进行阻止操作。
过滤器是双重结构。第一层过滤基于被阻止的URI。
_ignored_blockedURI_schemas = [ "http:",# We never use HTTP content so not a legit report "mxaddon-pkg",# maxthon addon packages "jar:",# firefox addons "file:",#we never insert file URIs into the page "tmtbff://",# ticketmaster toolbar? "safari",# safari extensions "chrome",# stuff like chromenull: chrome:// chrome-extension:// "webviewprogressproxy:",# added by browsers in webviews "mbinit:",# MapBuilder "symres:",# Norton "resource", ];
如果被阻止的URI以列表中任何一项开头,则忽略。第二层过滤基于被阻止URI的主体部分。
_ignored_blockedURI_hosts=[ "tlscdn", ".superfish.com", "addons.mozilla.org", "v.zilionfast.in", "widgets.amung.us", "xls.searchfun.in", "static.image2play.com", "localhost", "127.0.0.1", "guzzlepraxiscommune", "tfxiq", "akamaihd.net", #Dropbox doesn't use Akamai CDN "apollocdn", "worldssl.net", "shwcdn.net", "cmptch.com", "datafastguru.info", "eshopcomp.com", "hwcdn.net", ]
如果被阻止URI的主体部分包含上面的任何一个关键词,过滤器代码都不会将错误报告加入日志。当然,在使用该列表之前,必须保证在自己的网站中,没有使用列表中的任何一个域名。
修改CSP规则的扩展工具是另外一个噪声源。为了忽略这类错误,过滤器的设计同样也是基于违反的指令字段(violated directive field)。如果违反的指令字段包含“http:”或“:443”,报告将进行滤除,因为在规则中并不包含这些内容。为了做到这一点,我们考虑使用的一个方法是,在报告的URI中添加当前规则的hash表,之后只接受错误报告中的规则符合URI中hash表的报告。但是目前我们还没有将这种方法付诸实践。
查看英文原文: [CSP] On Reporting and Filtering
《他山之石》是InfoQ中文站新推出的一个专栏,精选来自国内外技术社区和个人博客上的技术文章,让更多的读者朋友受益,本栏目转载的内容都经过原作者授权。文章推荐可以发送邮件到editors@cn.infoq.com。