TEL: 180-210-69380

figma服务器端沙箱:虚拟机

Nov,14,2023 << Return list


沙箱选项如此之多,选择正确的一项是一项艰巨的任务。在这里,我们深入探讨沙箱的虚拟机 (VM) 安全模型,包括需要考虑的工程权衡以及我们如何在 Figma 中使用它们来实现安全隔离。

VM是一个来宾虚拟计算机,其行为类似于具有自己的内存、磁盘和 CPU真实物理计算机。

Seccomp可以限制程序允许进行的系统调用。

在Figma,我们并没有尝试完全防止安全漏洞,而是采用服务器端沙箱(也称为工作负载隔离)来最大限度地减少这些安全风险。服务器端沙箱概述中,我们介绍了应用程序沙箱的概念,解释了它的有用性,并简要讨论了三种不同的高级技术方法:VM容器和安全计算模式seccomp )。对于使用虚拟机进行沙箱,我们主要关心两个安全问题:

  • 虚拟机内部的恶意作业能否突破虚拟机?

  • 即使恶意作业无法突破虚拟机,它是否可以使用虚拟机的权限访问其他系统或以其他方式造成危害?

虚拟机安全模型

为了回答这些问题,我们必须检查虚拟机安全模型中两个主要的相关边界:虚拟机管理程序和虚拟机自身的权限。

虚拟管理程序管理虚拟机并允许您在一台物理机上同时运行多个虚拟机。

虚拟机逃逸是指虚拟程序突破虚拟机的隔离并访问主机系统。

首先,管理程序正确地将主机系统与来宾 VM 以及来宾 VM 与其他来宾 VM 分开。对于许多沙箱用例来说,这个安全边界绰绰有余,不太可能成为更广泛的安全系统中的薄弱环节。然而,由于虚拟机管理程序倾向于协调许多操作系统 (OS) 和硬件操作,因此它们通常会暴露出大型且复杂的攻击面。有时,漏洞允许来宾虚拟机接管主机(如虚拟机逃逸),或者与其他来宾交互或确定有关其他来宾的信息。


A castle projects an image of three towers.


裸机实例是需要访问硬件或服务器的工作负载。

涉及构建专门的虚拟机管理程序或需要彻底了解虚拟机管理程序攻击面的用例很复杂,但有许多像这样的资源可以提供有用的概述。

例如,大多数大型云基础设施即服务 (IaaS) 提供商(例如 AWS 或 Microsoft Azure)都依赖虚拟机作为隔离租户的关键原语。如果您的系统在此类云提供商中运行,并且您不限制自己使用裸机实例,那么您的安全模型无论如何都必须在某种程度上依赖虚拟机管理程序安全边界。

其次,除了虚拟机逃逸之外,仅仅将受损的工作负载放置在虚拟机内可能还不够。例如,如果虚拟机中的恶意作业仍然可以进行网络调用以窃取数据或使用虚拟机的凭据调用其他服务,则您将需要其他控制。虽然我们修改虚拟机管理程序本身的能力通常有限,但我们可以配置虚拟机的功能来减少接管虚拟机的恶意作业的影响范围。例如,您可以(并且应该)限制网络访问,最大限度地减少虚拟机联系其他服务的权限,并限制虚拟机凭据以及虚拟机本身的生命周期。


工程考虑

在我们对服务器端沙箱的介绍中

A millipede gets into a castle by going up through the drain into a pit with spikes. The pit stops it from getting out.


,我们分享了一系列问题,这些问题映射到您和您的团队考虑不同沙盒解决方案及其权衡的主要因素:环境、安全性和性能、开发成本和摩擦以及维护和运营开销。考虑到这些因素,我们来评估虚拟机。


环境

由于虚拟机可以运行成熟的操作系统,因此它们具有显着的优势:大多数工作负载可能几乎不需要修改即可在该环境中执行。如果您需要运行某些涉及第三方软件(例如办公生产力套件或 Web 浏览器)的工作负载(例如将文本文档转换为 PDF),您甚至可能需要完整的虚拟机。

安全性和性能

容器或 seccomp 等其他沙箱原语相比,创建和运行完整的虚拟机往往会对性能产生更大的影响。主要原因之一是虚拟机需要粒度隔离,而隔离每个工作负载意味着每个工作负载的设置和拆卸成本很高,并且等待虚拟机从冷启动准备就绪的延迟也会增加。保持可用 VM 工作线程的预热池有助于解决冷启动问题,但会增加开销 - 实施和操作这种编排系统很复杂。此外,与轻量级选项相比,完整虚拟机的性能影响通常与增加的货币成本相关。您可能会问自己是否每个单独的工作负载都需要隔离,或者跨不同工作负载(即属于同一用户的工作负载)进行某种程度的沙箱共享是否可以接受。

开发成本和摩擦

由于完整的虚拟机通常允许您运行整个操作系统,因此与限制性更强的沙箱技术相比,许多类型的工作负载几乎不需要任何修改就可以在虚拟机内部运行。Firecracker(一种由 Amazon 构建的专注于安全的 VM 技术)等专用 VM可能需要自定义运行时来支持您的工作负载。

维护和运营费用

总体而言,虚拟机通常不会使调试变得更加痛苦,也不会为主动修改工作负载代码的工程师增加太多额外的开发成本。有许多成熟的方法可以为工程师提供常用的调试技术,并且这些工具通常非常有用。

然而,管理、操作和编排沙箱虚拟机集群或服务可能很复杂。做好这项工作可能需要可靠性工程知识和经验。例如,直接管理虚拟机编排通常需要深入了解底层系统的核心内部结构,特别是跟踪每个虚拟机的状态,并针对意外的性能下降来源进行调整。根据性能限制,该编排系统还可能负责围绕哪些用户请求与哪些虚拟机关联进行复杂的路由决策。虽然虚拟机在许多情况下可以作为直接沙箱解决方案开箱即用,但它们通常需要额外的开发和维护成本。

figma" class="css-vsobh0" style="box-sizing: inherit; cursor: var(--cursorText); margin: 80px 0px 40px; font-family: __hexFranklinVariable_037dfd, __hexFranklinVariable_Fallback_037dfd; font-size: min(5vw, 4.5rem); font-variation-settings: "wght" 750, "wdth" 70; font-feature-settings: "ss01"; line-height: 1.04; letter-spacing: 0.005em; color: rgb(19, 19, 19); text-wrap: wrap; background-color: rgb(105, 184, 142);">我们如何在 Figma 使用虚拟机

在 Figma,对于适合基于虚拟化的沙箱的情况,我们依赖使用 Firecracker 的 AWS Lambda。虽然我们依靠 AWS Lambda 来处理虚拟化管理的大部分细节,但我们仍然需要做出有趣的、持续的权衡。例如,为了确保 Lambda 对于那些想要在同步核心服务路径中使用它们的人来说是一个可行的选择,AWS 选择重复使用同一租户中的各个虚拟机来处理多个请求:Firecracker 提供相当快的虚拟机启动时间,但是许多核心工作流程的管理费用仍然太高。然而,我们对这个级别的路由的控制很少。对于许多工作负载来说,这是一个合理的安全权衡。

在 Figma,我们使用 Lambda 来执行无状态处理功能,例如获取外部图像以在 Figma 画布中使用,或者获取链接元数据以及转换关联图像或调整其大小以在 figma.net.cn/lm2/3383.html">FigJam 中进行链接预览对于这些操作,低延迟非常重要——当用户将内容添加到 Figma 画布时,他们希望能够快速看到它此外,执行这些操作所涉及的大部分代码都以大型开源库的形式出现。一开始就很昂贵,并且需要大量的持续维护工作来维护分叉,以将它们适应不太通用的沙箱原语。

对于链接元数据获取器,我们经常需要调整图像大小或将其转换为 Figma 前端可以理解和渲染的格式。为此,我们从第三方链接获取数据并在 AWS Lambda 中运行图像处理库,这也意味着 Firecracker 虚拟机。由于此执行环境在生产 VPC 之外的 AWS 帐户中运行时没有任何特殊权限,因此利用我们的链接获取逻辑或 ImageMagick 中的漏洞将不会授予任何与 Figma 的内部服务通信或利用新位置接触外部任何内容的能力Lambda 执行环境。

与我们在 nsjail 方面的经验(我们在此详细介绍)不同,我们必须为这些虚拟化用例进行相对较少的沙箱调整。由于没有需要管理的系统调用 (syscall) 允许列表,因此无需担心很少评估的代码路径。话虽如此,我们始终需要避免一些陷阱。首先,Lambda 环境包括一个本地主机 HTTP 侦听器,该侦听器将为任何调用者提供触发 Lambda 的请求的内容,或者允许 Lambda 环境中的任何调用者伪造响应。虽然我们无法阻止 Lambda 中执行的代码调用此 API,但我们不希望服务器端请求伪造 (SSRF) 漏洞提供此功能,因此我们需要确保我们的应用程序代码不会向本地主机。其次,Lambda 在云环境中运行,而不是作为“原始”计算:可以轻松配置 Lambda,以便它们拥有特殊权限,无论是在内部网络中还是通过授予它们身份和访问管理 (IAM) 访问权限其他云资源。

通过我们的沙箱方法,我们还必须迭代性能和资源限制调整。当我们第一次实现此 Lambda 时,对其的调用可能需要长达 10 秒的时间,这比我们对此功能的预期延迟要高得多。随着 Lambda 运行时的升温,我们的平均延迟变得更低,但我们还必须投入直接的工程工作,以确保我们尽可能减少启动和处理成本,并尽量减少对 Lambda 并发限制的争用,这是一个共享的限制。 AWS 账户和区域中所有 Lambda 之间的配额。