写点什么

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

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

关注

评论

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

这些react面试题你会吗,反正我回答的不好

beifeng1996

前端 React

NFTScan 与 ET.XYZ 在 NFT API 数据层面进行深度合作

NFT Research

区块链 NFT web3

react20道高频面试题答案总结

beifeng1996

前端 React

19道高频vue面试题,顺便写一下自己的答案

bb_xiaxia1998

Vue 前端

融云员工服务台,跟“干不完”说再见

融云 RongCloud

IT职场

【云原生 | 从零开始学Kubernetes】六、Pod的镜像拉取策略与各种机制

泡泡

Docker 云计算 云原生 k8s 9月月更

数据库系统是什么?它由哪几部分组成?

乌龟哥哥

9月月更

前端面试经常被问的题目,自己总结了一下

loveX001

JavaScript 前端

VUE v-bind 数据绑定

HoneyMoose

Struts实现登录

Struts2 9月月更

[SpringBoot]多环境配置,配置文件分类

十八岁讨厌编程

Java 后端开发 9月月更

js高频手写题总结

helloworld1024fd

JavaScript 前端

跟我学Python图像处理丨带你掌握傅里叶变换原理及实现

华为云开发者联盟

Python 人工智能 企业号九月金秋榜

Code For Better 谷歌开发者之声——Google Cloud谷歌云

Fire_Shield

云原生 Google Cloud 9月月更

[SpringBoot]配置文件格式、yaml配置及读取

十八岁讨厌编程

Java 9月月更

2022-09-23:整数数组 stations 表示 水平数轴 上各个加油站的位置。给你一个整数 k 。 请你在数轴上增设 k 个加油站, 新增加油站可以位于 水平数轴 上的任意位置,而不必放在整数

福大大架构师每日一题

算法 rust 福大大

【云原生 | 从零开始学Kubernetes】五、Kubernetes核心技术Pod

泡泡

Docker 云计算 云原生 k8s 9月月更

自动化测试神器playwright的安装及常见问题解决

迷彩

playwright 学习记录 9月月更

深度剖析Istio共享代理新模式Ambient Mesh

华为云开发者联盟

云计算 云原生 后端 企业号九月金秋榜

SpringBoot初识

十八岁讨厌编程

Java 后端开发 9月月更

大数据调度平台Airflow(七):Airflow分布式集群搭建原因及其他扩展

Lansonli

airflow 9月月更

物联网实践分享

彭发红

Web3.0 杂谈 -#003(49/100)

hackstoic

Web3.0

INFINI 产品更新啦 20220923

极限实验室

elasticsearch console Gateway infini 极限实验室

JavaWeb核心之ServletContext

楠羽

Servlet 笔记 9月月更

Serverless遇到 FinOps: Economical Serverless

华为云开发者联盟

云原生 后端 企业号九月金秋榜

Http轮询分为长查询和短查询总结

知识浅谈

HTTP 9月月更

关于 Angular 应用 tsconfig.json 中的 lib 属性

汪子熙

typescript 前端开发 angular web开发 9月月更

Docker多阶段构建实战(multi-stage builds)

程序员欣宸

Docker 9月月更

TCP协议和UDP协议详细介绍

阿柠xn

TCP 计算机网络 协议族 UDP协议 9月月更

js常见手写题总结

helloworld1024fd

JavaScript 前端

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