【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

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:341716
用户头像

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

关注

评论

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

Flink 实践教程-进阶(7):基础运维

腾讯云大数据

flink 实战 流计算 Oceanus

Kubernetes 下部署 JMeter 集群

zuozewei

Jmeter 性能测试 1月月更

哲元科技×飞桨EasyDL|助力世界500强企业打造“灯塔工厂”,探索智能制造星辰大海

百度大脑

i人事CTO王景飞:i人事+计算巢,协同赋能HR业务

阿里云弹性计算

阿里云 计算巢

简单的线程池实现多线程对大文件的读取

CRMEB

RadonDB PostgreSQL on K8s 2.1.0 发布!

RadonDB

数据库 postgresql 开源 RadonDB

浪花过后,2022低代码该往哪儿走?

ToB行业头条

通证经济是更高层次的自由

CECBC

精彩回顾!| Google DevFest 2021 广州国际嘉年华

江湖老铁

markdown-it 插件如何写(二)

冴羽

前端 markdown vuepress markdown-it markdown-it插件

用11本白皮书搭建3座桥:联想企业科技集团让智能化转型不再有孤岛

脑极体

架构实战营:模块六作业

Geek_93ffb0

「架构实战营」

明道云助力东航食品营销数据整合

明道云

架构实战营-毕业设计

Beyond Ryan

流计算 Oceanus | Flink JVM 内存超限的分析方法总结

腾讯云大数据

flink 实战 流计算 Oceanus

StreamNative 联合传智教育推出免费 Apache Pulsar 中文视频教程

Apache Pulsar

大数据 开源 架构 云原生 Apache Pulsar

架构实战营-毕业设计

Beyond Ryan

使用APICloud AVM框架开发预约应用

YonBuilder低代码开发平台

前端框架 APP开发 APICloud 跨端开发 小程序开发

OpenMLDB在AKULAKU实时特征计算场景的应用

第四范式开发者社区

机器学习 大数据 OpenMLDB 特征平台

安全研究人员发现:Nanocore等多个远控木马滥用公有云服务传播

H

网络安全

Nacos电子书 读后感(一)

努力努力再努力

1月日更

网络安全kali渗透学习 web渗透入门 ARL资产侦察灯塔系统搭建及使用

学神来啦

低代码实现探索(二十六)移动端H5开发

零道云-混合式低代码平台

低代码实现探索(二十七)低代码如何继承传统

零道云-混合式低代码平台

使用hydra对端口进行爆破

喀拉峻

喜报!东方证券携手博睿数据荣获《金融电子化》2021科技赋能金融业务突出贡献奖

博睿数据

【网络研讨会】“专家面对面”-MongoDB模式设计

MongoDB中文社区

mongodb

征文投稿丨使用轻量应用服务器部署Hadoop云集群

阿里云弹性计算

hadoop 轻量应用 征文投稿

消息队列 RocketMQ 遇上可观测:业务核心链路可视化

阿里巴巴云原生

阿里云 RocketMQ 云原生 消息队列 可观测

云信小课堂|如何实现音视频安全检测?

网易云信

安全 音视频

12月云短信报告出炉,阿里云闯进前三

博睿数据

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