在Firefox 100中改进进程隔离的介绍

344 阅读10分钟

简介

火狐浏览器使用 多进程模型 ,以提高浏览时的安全性和稳定性。网络内容(如HTML/CSS和Javascript)是在独立的进程中呈现的,这些进程与操作系统的其他部分隔离,并由一个有权限的父进程管理。这样,利用内容进程中的错误的攻击者所获得的控制量是有限的。

自从我们部署这个模型以来,我们一直在努力提高内容进程的隔离度,以进一步限制攻击面。这是一项具有挑战性的任务,因为内容进程需要访问一些操作系统的API才能正常运行:例如,它们仍然需要能够与父进程对话。

在这篇文章中,我们想进一步探讨一下我们已经达到的最新的主要里程碑。 Win32k Lockdown, 它大大降低了内容进程在Windows上运行时的能力。连同之前发货的 两个主要工作(FissionRLBox),这完成了一连串的大跃进,将大大改善Firefox的安全性。

尽管 Win32k Lockdown 是一项针对Windows的技术,但它之所以成为可能,是因为Mozilla在四年前就已经对Firefox的安全边界进行了重大的重新架构,这使得在其他操作系统上也能取得类似的安全进步。

目标:Win32k锁死

火狐浏览器在Windows上运行时,对渲染网页内容的进程有相当多的限制,允许它们做什么。不幸的是,在默认情况下,它们仍然可以访问整个Windows API,这就打开了一个巨大的攻击面:Windows API由许多部分组成,例如,处理线程、进程和内存管理的核心部分,还有网络和套接字库、打印和多媒体API等等。

我们特别感兴趣的是 win32k.sys API, 它包括许多图形和小工具相关的系统调用,这些调用有被利用的历史。进一步追溯到Windows的起源,这种情况可能是微软为了提高Windows 95和NT4前后的性能,将许多原来在用户模式下运行的操作转移到内核中的结果。

这些API可能从来没有被设计成在这种敏感的环境中运行,因此一直是黑客突破应用程序沙箱进入内核的传统目标。

在Windows 8中,微软引入了一个名为 PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY的新缓解措施 ,应用程序可以用它来禁止访问win32k.sys系统调用。这是个很长的名字,需要不断重复,所以我们以后会用我们的内部称呼来称呼它:"Win32k Lockdown"。

所需的工作

在网络内容进程(最容易受到潜在的敌对网页和 JavaScript 影响的进程)上翻开 Win32k Lockdown 标志,意味着这些进程自己不能再执行任何图形、窗口管理、输入处理等操作。

为了完成这些任务,这些操作必须被遥控到具有必要权限的进程,通常是能够访问GPU并处理合成和绘图的进程(以下称为GPU进程),或具有特权的父进程。

绘制网页。WebRender

对于网页内容的绘制,Firefox在历史上使用了各种与Windows API交互的方法,从使用现代的基于Direct3D的纹理,到退回到GDI表面,以及最终下降到纯软件模式。

这些不同的选项将需要相当多的工作来遥控,因为大多数图形API在Win32k Lockdown中是被禁止的。好消息是,从Firefox 92开始,我们的渲染堆栈已经切换到 WebRender,它将所有的实际绘制工作从内容进程转移到GPU进程中的WebRender。

因为有了WebRender,内容进程不再需要直接与平台的绘图API交互,这就避免了任何与Win32k Lockdown有关的问题。WebRender本身也被部分地设计成 与游戏引擎更相似,因此,更不容易受到驱动错误的影响

对于剩下的那些太破的驱动程序,它仍然有一个 完全基于软件的模式,这意味着我们没有更多的退路需要考虑。

网页的绘制。Canvas 2D和WebGL 3D

Canvas API 为网页提供了绘制2D图形的能力。在最初的Firefox实现中,这些JavaScript API是在Web Content进程中执行的,对Windows绘图API的调用是直接从相同的进程中进行的。

在Win32k Lockdown的情况下,这不再可能,所以 所有的绘图命令都是 通过IPC在GPU进程中记录和回放的方式进行远程操作

尽管最初的实现有很好的性能,但还是有一些网站的报告说出现了性能倒退(那些变得更快的网站一般都没有抱怨!)。一个特别的痛点是 反复 调用 getImageData()的应用程序 :将Canvas远程化意味着现在必须从另一个进程获得GPU纹理并通过IPC发送。

在 getImageData 在一帧开始时被调用的情况下,我们通过检测这种情况并主动准备好正确的表面,使从 GPU 复制的速度更快,从而弥补了这一点。

除了用于绘制2D图形的Canvas API,网络平台还提供了一个 用于绘制3D图形的API,称为WebGL。WebGL是一个重状态的API,所以正确有效地同步子代和父代(以及父代和驱动)需要 非常 小心

WebGL最初在Content中处理所有的验证,但随着对GPU的访问和相关攻击面的移除,我们需要在子代和父代之间设计一个强大的验证API,以获得全部的安全利益。

(表格的(非)本地主题设计

HTML网页有显示表单控件的能力。虽然绝大多数网站都 为这些表单控件提供了 自定义的外观和样式,但并不是所有的网站都这样做,如果它们不这样做,你就会得到一个输入GUI小部件,它的样式就像(而且最初是!) 操作系统的一个 本地元素

从历史上看,这些都是通过在内容进程中调用适当的操作系统小部件API来绘制的,但在Win32k Lockdown下,这些都是不可用的。

这并不容易通过远程调用来解决,因为widget本身有无限多的尺寸、形状和风格可以交互,并且需要对用户的输入和派发的信息做出反应。我们决定让Firefox 以一种跨平台的方式 来绘制表单控件

虽然改变表单控件的外观会对网络兼容性产生影响,而且有些人喜欢更原生的外观--在少数不对控件应用自己的样式的页面上--但Firefox的方法与其他浏览器采取的方法是一致的,可能是因为非常相似的考虑。

滚动条是一个特别的痛点:我们不想以与其他用户体验不同的方式来绘制内容窗口的主滚动条,因为嵌套的滚动条会以不同的样式显示出来,看起来很别扭。但是,与相当少见的没有样式的窗体部件不同,主滚动条在大多数网页上都是可见的,而且因为它在概念上属于浏览器的用户体验,我们真的希望它看起来是原生的。

因此,我们决定把所有的滚动条都画成与系统主题相匹配的样子,尽管如果连 操作系统的供应商都不能决定什么是 "原生 "的样子,那就有点悬而未决 了。

最后的障碍

断线

有了上述变化,我们认为我们已经解决了所有会访问win32k.sys中的图形和小工具API的通常嫌疑人,所以我们开始在禁用win32k系统调用的情况下运行完整的Firefox测试套件。这至少造成了一次意外的失败。 在试图 为某些具有复杂脚本的语言 寻找换行符时,Firefox 崩溃了

虽然Firefox能够正确地确定大多数语言的多字节字符流的词尾,但对泰语、老挝语、藏语和高棉语的支持是不完善的, 在这些情况下,Firefox可以要求操作系统 为其处理换行问题 。但至少在Windows上,这样做的功能被Win32k Lockdown开关所覆盖。糟糕!"。

目前 正在努力将ICU4X纳入其中 ,并将所有i18n相关的功能建立在此基础上,这意味着Firefox将能够完美地处理所有脚本,而无需涉及操作系统,但这是一项重大努力,而且不清楚它是否最终会推迟win32k锁定的推出。

我们做了一些实验,试图通过IPC转发断线。最初,这有不好的性能,但当我们 添加了缓存后 ,性能是令人满意的,有时甚至提高了,因为现在在许多情况下可以避免操作系统调用。

DLL加载和第三方交互

禁用win32k.sys访问的另一个复杂性是,如此多的Windows功能在默认情况下是可用的,必须采取具体的努力来确保相关的DLLs在启动时不被加载。例如,Firefox本身不会加载包含一些win32k APIs的user32 DLL,但 注入的第三方DLL有时会加载。这就造成了问题,因为 COM初始化特别使用win32k调用来获取窗口站和桌面 ,如果DLL存在的话。启用Win32k锁定后,这些调用将失败,默默地破坏COM和依赖它的功能,如我们的无障碍支持。

在Windows 10 Fall Creators Update及以后的版本中,我们有一个修复方案,可以阻止这些调用,并强制进行回退,从而保持一切正常工作。我们测量过, 在打开新标签时,不加载DLLs会导致大约15%的性能提升 ,在安全利益之上增加了一个不错的性能奖励。

余下的工作

正如上一节所暗示的,Win32k Lockdown最初将在Windows 10 Fall Creators Update及以后的版本中推出。在Windows 8和未打补丁的Windows 10(不幸的是,这似乎正在使用!)上,我们仍在测试对第三方DLLs干扰情况的修复,所以对这些的支持将在 未来的版本中出现 。

对于Canvas 2D的支持,我们仍在 研究改善 进程切换时退步 的应用程序的性能 。同时,我们正在进行试验,看看能否 通过 WebGL 实现 Canvas 2D 的硬件加速 ,这将增加 2D 和 3D 实现之间的代码共享,并利用现代视频驱动为 3D 情况进行更好的优化。

总结

在像Firefox这样的大型应用中,对责任分工的重大改变进行改造,是一个巨大的、多年的工程挑战,但为了提高浏览器的安全性并继续保证我们用户的安全,这是绝对必要的。我们很高兴能够完成这一任务,并向您展示Firefox 100的成果。

其他平台

如果你是一个Mac用户,你可能会想知道是否有类似于Win32k Lockdown的东西可以在macOS上完成。你会是对的,我有个好消息要告诉你:我们已经悄悄地 发货了, 在Firefox 95中阻止了对WindowServer的访问 ,提高了安全性,并将进程启动的速度提高了约30-70%。这也是因为上述的远程WebGL和非原生主题工作而成为可能。

对于Linux用户, 我们删除了从内容进程到X11服务器的连接,这阻止了攻击者对不安全的X11协议的利用。虽然Linux发行版已经转向更安全的Wayland协议作为默认协议,但我们仍然看到很多用户在使用X11或XWayland配置,所以这绝对是一个很好的功能,在Firefox 99中也有。