写点什么

Dropbox 的 Web 安全防护策略之四:第三方接入与权限分离

  • 2015-12-15
  • 本文字数:3197 字

    阅读完需:约 10 分钟

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

在本系列之前的几篇文章中,我们讨论了 Dropbox 配置 CSP 的经验,着重介绍了控制脚本源的 script-src 指令。通过锁定脚本源白名单、配置随机数源以及限制 unsafe-eval 风险等措施,Dropbox 的 CSP 规则有效地缓解了 XSS 注入攻击。在所支持的浏览器中,只有来自于我们自己的网站、CDN 或其他受信第三方的代码可以在 Dropbox 的网页应用中运行。

然而,配置 CSP 同时使用第三方接入又有其特有的风险与挑战。在本篇文章中,我们会讨论如何用 HTML5 权限分离的方法来解决此问题。

第三方接入的风险

首先举一个例子来说明在我们网站上运行的第三方接入代码:企业版Dropbox 中有一个 SnapEngage 提供的即时聊天小工具,根据网页应用与 SnapEngage 集成的机制,我们在 HTML 页的脚本节点中插入了以下代码。

复制代码
var se = document.createElement('script');
se.type = 'text/javascript';
se.async = true;
se.src = '//storage.googleapis.com/code.snapengage.com/js/' + chatId + '.js';
se.onload = se.onreadystatechange = function() { ... //elided
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(se, s);

上面的代码生成了指向 SnapEngage 库的脚本节点,同时设置了 onload 处理器,并将节点插入到页面中。载入的 JavaScript 库接下来生成显示聊天工具的标记和相关的事件处理器,并把它们插入到页面中。

这一过程存在着两个关键的问题。首先,聊天工具的标记和事件处理器并未使用 CSP 规则,因此,如果聊天工具使用了 eval 或内联事件处理器,我们的 CSP 规则便会阻止启动聊天工具。当我们第一次在 Dropbox 网站上为 script-src 配置随机数时,嵌入了聊天工具的页面不得不禁用 CSP 规则,这也就增加了页面遭受 XSS 攻击的风险。

另一个问题是一个不易察觉的威胁:该过程增加了 Dropbox 的可信计算基,最终包含了SnapEngage 的服务器。根据同源策略,所有运行在www.dropbox.com 源上的代码拥有相同的权限。增加可信计算基实质上隐性地增加了安全风险。未来的网络平台提升方法可以降低这一类的安全风险,但该方法目前仍在万维网联盟(W3C)内部讨论。

我们很了解上述风险,Dropbox 第三方接入的提供者也对自身进行了全面审查,并且强制执行了安全条约。但在实际中,仍然存在某些第三方提供者并未认真执行安全检查的情况,本着对用户负责的态度,我们认为此类数据安全风险过高无法接受,必须采取相应措施降低风险。

对此,一个可行的解决方案是,只将接入代码复制到我们的服务器中,同时修改聊天工具,使之去掉内联事件处理器。然而这种侵入式的解决方法代价巨大,更为糟糕的是,只要聊天工具升级更新,Dropbox 就必须人工进行检查和提交代码。如果将这个步骤自动完成,那么同样会产生许多安全隐患。

补救方法:权限分离

我们使用权限分离的方法来解决第三方接入所带来的问题,其核心思想很简单:在无权限的源(origin)中运行第三方代码,避免了直接在Dropbox 源中运行第三方代码。第三方代码通过iframe 接入网站,iframe 间的通信使用postMessage 函数。Dropbox 源提供更小的受信API,在不降低安全性的前提下保证了相关功能。

这同 OpenSSH Google Chrome 的权限分离架构很类似,无权限的子进程与无权限的源通信,有权限的进程与有权限的(Dropbox)源通信。不过与库应用中使用的 IPC 机制不同,我们使用 postMessage 实现 iframe 间的通信。

具体来看一下 SnapEngage 接入到底怎样做到了权限分离。当载入一个含有 SnapEngage 聊天工具的网页时, https://www.dropbox.com 源中的代码生成一个指向 https://www.dbxsnapengage.com 的 iframe。接下来,dbxsnapengage.com 上的代码载入 SnapEngage 聊天工具。iframe 自带的 CSS 隐藏聊天工具的边框,看起来聊天工具便和 Dropbox 网页天衣无缝地组合在了一起。

当然,这种方法的效率并不高。为了维护相关功能,聊天工具需要和主页集成。比方说,我们希望只在用户点击页面顶端的“Chat”按钮时,聊天工具才显示出来。之前的 JavaScript 代码通过监测“Chat”按钮上的按键动作,调用 startSupportChat 函数来实现该功能。

复制代码
function startSupportChat() {
SnapEngage.setWidgetId(SUPPORT_ID);
SnapEngage.setUserEmail(chatData.Email, true)
SnapEngage.startChat("How can we help you today?")
}

startSupportChat 函数会调用初始化聊天功能的相关 SnapEngage 代码。由于 SnapEngage 代码运行在 dbxsnapengage.com 上,这个函数并没有产生任何效果,也不存在于 www.dropbox.com 当中。我们对此的做法是,在 www.dropbox.com 上修改代码来给 iframe 发送消息。

复制代码
DropboxSnapEngage.startSupportChat = function() {
this.chatRequested = true;
DropboxSnapEngage.showSnapEngageIframe();
return DropboxSnapEngage.sendMessage({
'message_type': 'startSupportChat',
'chatData': this.chatData
});
};
DropboxSnapEngage.sendMessage = function(data) {
var content_window;
content_window = DropboxSnapEngage.getSnapEngageIframe().contentWindow;
return content_window.postMessage(data, this.SNAPENGAGE_IFRAME_ORIGIN);
};

上述代码给 dbxsnapengage.com 的 iframe 发送消息。接着,dbxsnapengage.com 通过定义下面的 postMessage 事件处理器来调用 startSupportChat 函数。

复制代码
function receiveMessage(event) {
if (!validOriginURL(event.origin)) return;
var data = event.data
switch (data.message_type) {
//elided ...
case "startSupportChat":
startSupportChat();
break;
//elided ...
}
}

最终的效果为,点击“Chat”按钮后将显示 iframe,并给聊天工具代码发送消息以启动聊天功能。所有的聊天工具代码都运行在无 Dropbox 权限的 dbxsnapengage.com 源中。

以上所讲的仅仅是一个例子,我们在 Dropbox 网站中不同的位置都使用了权限分离的方法,有效地降低了第三方接入(例如,支付服务提供商的接入)所带来的风险。另外,作为第三方提供者的 SnapEngage 不需要做任何的改动,可以继续使用内联事件处理器。这个设计的特点虽然看起来微不足道,但事实上非常重要。我们拥有并运营着 dbxsnapengage.com 域名,也开发完成了跨权限的 postMessage API。

查看英文原文: [CSP] Third Party Integrations and Privilege Separation

编后语

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


感谢魏星对本文的审校。

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

2015-12-15 17:342024
用户头像

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

关注

评论

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

量化交易策略系统搭建,合约跟单交易系统软件开发

V\TG【ch3nguang】

量化交易系统开发 合约跟单

R语言之基础绘图

timerring

R 语言

“算力+运力”扇动双翼,制造算力时代的蝴蝶效应

脑极体

运力 全光运力

Programming abstractions in C阅读笔记:p132-p137

codists

对线面试官 - MQ之如何保证消息的顺序性及消息积压问题

派大星

MQ Java 面试题

响应式编程——初识 Flux 和 Mono

java易二三

Java 程序员 计算机 程序

快速测试Mybatis复杂sql,无需启动spring

java易二三

Java 编程 程序员 计算机 科技

生成式AI浪潮下,那些不可忽视的安全问题

网安云

AI安全 系统安全 开源治理 软件系统安全

活动回顾丨云原生技术实践营长沙站(含 PPT)

阿里巴巴云原生

阿里云 云原生

美团 Flink 资源调度优化实践

Apache Flink

大数据 flink 实时计算

深入解析G1垃圾回收器

Java随想录

Java JVM

IPQ4019 IPQ4029 IPQ6010|IIOT|5G and WiFi 6:Application in Business and Industry

wallyslilly

IPQ4019 IPQ6010 ipq4029

​ iOS加固保护新思路

iOS 架构RxSwift 重签名

百度垂类离线计算系统发展历程

百度Geek说

数据处理 计算引擎 架构优化 企业号 8 月 PK 榜 搜索架构

SRE方法论之减少琐事

不思jo

SRE 运维‘ #运维

最强远程管理 Royal TSX for Mac激活+补丁教程

胖墩儿不胖y

远程办公 远程软件 Mac软件 远程工具

可观测系统实践:基于海量数据的采集优化方案

博文视点Broadview

数字化转型与架构-架构设计篇|建模之数据模型

数字随行

数字化转型

01.崩溃捕获设计实践方案

杨充

深入解析ZGC垃圾回收器

Java随想录

Java JVM

Apache RocketMQ 5.0 消息进阶:如何支撑复杂的业务消息场景?

阿里巴巴云原生

Apache 阿里云 RocketMQ 云原生

深入解析CMS垃圾回收器

Java随想录

Java JVM

数智化转型背景下的火山引擎大数据技术揭秘

字节跳动数据平台

数据库 大数据 数字化建设 企业号 8 月 PK 榜

Dropbox的Web安全防护策略之四:第三方接入与权限分离_安全_张天雷_InfoQ精选文章