写点什么

Dropbox 的 Web 安全防护策略之二:unsafe-inline 指令和随机数配置

  • 2015-12-01
  • 本文字数:3785 字

    阅读完需:约 12 分钟

【编者的话】Dropbox 的 Web 安全防护措施之一是使用基于内容的安全策略(CSP)。Dropbox 的安全工程师 Devdatta Akhawe 通过四篇文章,介绍了 CSP 在 Dropbox 中推广的细节和经验。Dropbox 的 CSP 原则大大减少了 XSS 和内容注入攻击。不过,大规模使用比较严苛的 CSP 规则将面临诸多挑战。我们希望通过这四篇 CSP 系列文章,将 Dropbox 在实践 CSP 过程中的收获分享给广大开发社区朋友。第一篇文章主要介绍如何在规则中设置报表筛选管线来标记错误;第二篇介绍 Dropbox 如何在上述规则中配置随机数及缓解unsafe-inline带来的安全风险;第三篇介绍如何降低unsafe-eval造成的风险,以及介绍 Dropbox 所开发的开源补丁;最后一篇介绍在权限分离机制下,如何减小第三方软件整合时的风险。本篇是该系列文章的第二篇,主要介绍 Dropbox 的随机数配置,还有 unsafe-inline 指令所带来的问题及解决方法。

第一篇文章中,我们讨论了如何筛选错误报告及如何利用CSP 为网站配置内容源白名单。通常而言,白名单中最重要的内容源是代码源,代码源由 script-srcobject-src指令确定。标准的 CSP 配置一般含有一个受信任域名的列表,其中包括主网站名和可靠 CDN 等,它们由script-src及其他诸如unsafe-inlineunsafe-eval的指令给出。

这种规则阻止了随意注入的第三方脚本,但又由于有unsafe-inline这项指令存在,它并不能有效地防止 XSS 攻击。如果读者对unsafe-inlinenonce-src尚不熟悉,建议参阅这篇介绍文章。简而言之,CSP 默认阻止所有内联脚本区块和内联事件( < div onclick="somescript" >),加强了代码和数据的分离。所有运行在网页中的代码必须来自白名单中的源所提供的脚本文件。这样便大大降低了 XSS 攻击的风险,但同时也需要巨大的移植工作量。

为了使移植变得简便,规则中允许一类特殊的源指令句法,它适用于script-srcstyle-src指令,如果含有匹配的随机数属性,那么则接受内联内容。这样, script-src源列表中含有nonce-randomnumber的规则就可以允许执行将“randomnumber”作为随机数属性值的脚本标记。随机数句法是 CSP2 的一部分,现在仅仅在 Chrome 和 Firefox 中支持。而在其他浏览器中,使用内联脚本标记需要用unsafe-inline使能所有内联脚本。

本篇文章将讨论我们在 Dropbox 网站上配置随机数的经验。在进入细节讨论之前,必须强调 CSP 只是一项缓解措施,并不能取代严格的验证及清理净化工作。Dropbox 服务器和客户端分别使用的库是 Pyxl React ,客户端的 HTML 清理使用的库则是 DOMPurify

配置脚本随机数

配置脚本随机数包含两个步骤:一、给所有内联脚本标记加上对应的随机数;二、移除所有内联事件处理器。Dropbox 使用 Pyxl 生成服务器端的 HTML。Pyxl 将 HTML 标签转换为 Python 对象,在清理过程中自动去除非可信数据。我们调整了一些 Pyxl 清理代码,以便在脚本标记中插入正确的脚本随机数。

第二步移除内联事件处理器比较困难。有较长的一段时间我们极力反对使用内联事件处理器,Dropbox 上新写的代码也没有它们,但这仍然造成了大量旧代码没有办法移植。为了减少过渡阶段的工作量,我们决定自动重写内联事件处理器来使用内联脚本标记。最基本的例子如下,原来的代码<div id="foo” onload="somescript">变为:

复制代码
<div id="foo"><!-- if id is absent, we create a unique id -->
<script>
// The nonce in the script tag above will be
// inserted during Pyxl serialization
function(){
var e = document.getElementById(foo);
e.addEventListener("load", function(ev){
// ...somescript..
});
}();
</script>

上述例子有几个值得关注的点。首先,我们使用了即时调用函数表达式,这样不会造成全局命名空间的混乱。第二,我们插入了一个脚本标记,它在原本的标记打开后加入了onload事件处理器。通常的加入操作是在原来的 div 元素结束或DOMContentLoaded事件之后,虽然它们也可能有很好的特性,但我们修改后的代码已经很接近浏览器原来的性能,因此这里我们使用的方法适用于自动转换。

读者们可能仍然会有疑问:以上转换没有在onload代码中修复已有的 XSS 攻击,所以并不是完全安全的转换。然而,我们认为这种危险是在可接受范围内,因为像 Pyxl 之类的系统,已经可以很好地识别并阻止在服务器的代码中的 XSS。另外,随着时间的推移,我们仍将舍弃内联事件处理器,从而彻底规避这类风险。

通过上述的代码转换,只有在我们掌控中的内联脚本和事件处理器会执行。如果一次攻击尝试插入事件处理器(比如使用了 DOMXSS 等),支持随机数属性的浏览器将会阻止这类攻击。

内联脚本错误报告

和所有的 CSP 配置一致,推出一个新的随机数属性通常的做法是先在 report-only 模式下运行。Dropbox 使用 report-only 模式将近一个月。同样也和内容源错误报告一样,内联脚本错误中的噪声滤除也十分重要。

除了上篇文章中提到的技巧,Chrome 通过发送另外两项内容域(fields)来辅助识别内联脚本错误:脚本样本和源文件。脚本样本对于代码库中的快速查找十分关键,因为在本地重现问题较为困难。源文件则指的是通过 DOM API 插入内联脚本的 JavaScript 源文件。在筛选内联脚本错误阶段,我们过滤掉所有源文件域为 URI 的报告,这类错误报告不属于当前讨论的应用范围(广告插入和扩展工具是一类普遍的错误源)。类似地,参照 Neil 的建议,有些报告的脚本样本中包含的明显不是自己应用的代码(比如,脚本中包含字符串“lastPass”),我们也过滤掉了这一类错误报告。

Firefox 有一个程序缺陷:即便 nonce src允许执行内联脚本,Firefox 仍会上报错误,同时也在执行代码。因此我们建议,为了减少噪声,在配置随机数时删除 Firefox 的report-uri

更新:这个程序缺陷已经修复了!不过修复的版本是 2015 年十月发布的 Firefox 43,我们建议在 2016 年 1 月之前,不要为 Firefox 发送report-uri

利用合适的过滤器,我们给我们的规则配置了随机数源,而且开始查找错误并修复。对于像 Dropbox 这样巨大的规模和所拥有的代码库来说,这个过程十分枯燥。但是这项任务的回报值得我们做出努力,而且工作量也并非无法计算。经过几周的努力,我们成功地在执行模式下配置了nonce-src

无随机数支持下 DOMXSS 攻击的缓解

比较可惜的是,随机数源是 CSP2 中的功能。虽然 Chrome 和 Firefox 已经支持随机数源一段时间了,但 Safari 及 Edge 仍未支持。Safari 和 Edge 都没有随机数源句法,却强化了unsafe-inline源表达式。为了使我们的网页应用性能更好,我们使用了另一个技巧:

复制代码
document.addEventListener('DOMContentLoaded', function () {
var metaTag = document.createElement('meta');
metaTag.setAttribute('http-equiv', 'Content-Security-Policy');
metaTag.setAttribute('content', "script-src https: 'unsafe-eval';");
document.head.appendChild(metaTag);
});

简单地说,在浏览器执行所有 HTML 和同步脚本(包括内联脚本)后,激发 DOMContentLoaded 事件。在此之后,其他的 JavaScript 任务和事件进行排队,或者激发其他的 onload 处理器。随后的操作性能得到最大化,我们不再同时执行远程脚本,所以大部分 JavaScript 代码都在DOMContentLoaded之后执行。

上面展示的代码在DOMContentLoaded激发之后,插入了第二代 CSP 规则。需要特别说明的是,第二代 CSP 规则没有“unsafe-inline”。浏览器处理多个 CSP 规则时会强制遵循所有规则,只有符合全部规则的代码才能够得以执行。因此,在DOMContentLoaded事件激发之前,Safari 和 Edge 仅在初始 HTML 中解析并支持内联脚本。DOMContentLoaded激发之后,这两个浏览器便停止支持内联事件处理器。

设想一下,在某次攻击插入了含有恶意有效载荷(<div onclick=alert(1)>)。Chrome 和 Firefox 中的规则包含标头传递的随机数,可以阻止内联 onclick。而在 Safari 和 Edge 中,第一个规则允许onclick处理器,DOMContentLoaded事件后插入的第二个规则阻止onclick。尽管这种保护相对于支持随机数源的浏览器中的保护措施较为薄弱,但它仍然阻止了大量的 DOMXSS 攻击。

最后的思考

上面提到的方法有效地缓解了 Dropbox 网页应用受到的 XSS 攻击。在 Chrome、Firefox、Safari 还有 Edge 等浏览器中,我们的大量用户受到的网页攻击也得到了适当地减轻。我们修复了所有注入漏洞,也为我们大多数用户修筑了二次防线以抵御更强的注入攻击。

配置像 CSP 这样重要的工程,尤其还要舍弃“unsafe-inline”,需要全公司的鼎力支持。感谢参与该项目的所有 Dropbox 成员,特别是安全工程团队的小伙伴们。这篇文章是实践 CSP 系列文章中的第二篇。下一篇,我们将介绍在规则中加入unsafe-eval的影响,以及如何它所带来的降低风险。

查看英文原文: [CSP] Unsafe-inline and nonce deployment

编后语

《他山之石》是 InfoQ 中文站新推出的一个专栏,精选来自国内外技术社区和个人博客上的技术文章,让更多的读者朋友受益,本栏目转载的内容都经过原作者授权。文章推荐可以发送邮件到 editors@cn.infoq.com。


感谢魏星对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群(已满),InfoQ 读者交流群(#2))。

2015-12-01 16:393442
用户头像

发布了 268 篇内容, 共 122.6 次阅读, 收获喜欢 24 次。

关注

评论

发布
暂无评论
发现更多内容

GaussDB,连续五次No.1!

平平无奇爱好科技

音乐人解密:究竟是如何一步一步成为音乐人的?

懒得勤快

国产芯片开发为什么这么难?2023 中国芯片开发者调查报告发布

博文视点Broadview

中国振华刘昕:携手用友打造电子行业的数智化平台,服务全行业

用友BIP

2023用友BIP技术大会

再识华为云数据库——GaussDB

轶天下事

Ambient Mesh:Istio 数据面新模式

华为云开发者联盟

云原生 华为云 华为云开发者联盟 企业号 6 月 PK 榜

GaussDB存储过程介绍

平平无奇爱好科技

华为云GaussDB助力MetaERP构建“收入成本”产品,高效支撑华为多业务

轶天下事

财务共享管理体系助力企业卓越发展

用友BIP

财务共享

什么样的企业需要建设财务共享服务中心?

用友BIP

财务共享

软件测试/测试开发丨App自动化测试学习笔记

测试人

程序员 软件测试 测试开发 app自动化测试

硬核!阿里P8呕心沥血5年总结的Java面试速成手册开源一天上榜首

Java你猿哥

Java 微服务 算法 多线程 ssm

重学 Java 设计模式:实战建造者模式

Java你猿哥

Java 设计模式 ssm 计算机

全量通过!华为云GaussDB首批完成信通院全密态数据库评测

轶天下事

听说最近AI应用爆了?!来AI Studio玩转大模型应用

飞桨PaddlePaddle

百度飞桨

手把手实践丨基于STM32+NBIOT+华为云IOT设计智能井盖

华为云开发者联盟

云计算 华为云 华为云开发者联盟 企业号 6 月 PK 榜 智能井盖

软件测试/测试开发丨App自动化测试学习笔记分享

测试人

程序员 软件测试 测试开发 app自动化测试

身未动心已远,AI带你流浪地球

华为云开发者联盟

人工智能 华为云 华为云开发者联盟 企业号 6 月 PK 榜

GaussDB数据类型介绍

轶天下事

GaussDB数据类型转换介绍

平平无奇爱好科技

墨天轮专访TDengine陶建辉:坚持做难而正确的事,三次创业成就不悔人生

墨天轮

数据库 tdengine Influxdb 时序数据库 国产数据库

ChatGPT 之后,B 端产品设计会迎来颠覆式革命吗?| Liga妙谈

LigaAI

交互设计 产品设计与思考 tob产品 ChatGPT 企业号 6 月 PK 榜

GaussDB为什么成为游戏行业的心头爱?

平平无奇爱好科技

阿里工程师手打的MySQL学习笔记,轻松拿捏MySQL

小小怪下士

Java MySQL 程序员

降本增效,StarRocks 在同程旅行的实践

StarRocks

数据库 大数据 数据仓库 湖仓一体 大数据 开源

亿视电子基于PolarDB-X打造能源数字基座实践

阿里云数据库开源

MySQL 数据库 分布式 阿里云; PolarDB-X

GaussDB如何给世界一个更优选择?

平平无奇爱好科技

GaussDB数据库事务介绍

平平无奇爱好科技

华为云GaussDB入选“2022年数字技术融合创新应用解决方案”

轶天下事

后疫情时代,国际形势向好,企业出海如何把握风险管控?

用友BIP

中企出海

ChatGPT热度不减!华为宣布入局,盘古GPT能否大杀四方!

加入高科技仿生人

低代码 数智化 ChatGPT 文心一言 通义千问

Dropbox的Web安全防护策略之二:unsafe-inline指令和随机数配置_安全_张天雷_InfoQ精选文章