User | Access |
|
|
|
|
|
|
|
|
Current User
BUILTINUsers
Everyone
NT AUTHORITYINTERACTIVE
Logon SID
并添加以下受限制的SID: BUILTINUsers
Everyone
NT AUTHORITYRESTRICTED
Logon SID
将当前用户组和RESTRICTED受限SID结合在一起,就可以授予对沙箱进程或线程的完全访问权限。 要了解为什么能够打开另一个内容进程是一个问题,我们必须了解Chromium沙箱如何启动一个新进程。由于将主令牌分配给新进程的方式,一旦进程启动,就无法再更改为其他令牌。在这里可以做一些事情,例如删除特权和降低完整性级别,但是无法删除组或添加新的受限SID。 一个新的沙盒进程需要进行一些初始化,这需要比受限沙盒需要更多的访问权限,因此Chromium使用了一个技巧。它为初始线程分配了一个更高特权的模拟令牌,以便初始化以更高的特权运行。对于L5,初始令牌的级别为USER_RESTRICTED_SAME_ACCESS,它仅创建不是禁用组且所有普通组都添加了受限的SIDs。这使得令牌几乎等同于普通令牌,但是被认为是受限的。如果“主令牌”受到限制,但“模拟令牌”没有受到限制,则Windows将阻止设置令牌。 一旦完成所有初始化,就可以通过调用沙箱目标服务中的LowerToken函数来删除模拟令牌。这意味着有一个时间窗口,从新的沙盒进程开始到调用LowerToken时,该进程实际上在没有沙盒的情况下运行,除了具有低IL之外。如果您可以在删除模拟令牌之前劫持执行程序,则可以获得足够的特权,进行沙箱逃逸。 与Chrome GPU处理不同,Firefox在正常使用期间会创建新的内容进程。仅仅创建一个新的标签就可以产生一个新的进程。因此,当在创建新进程的时候进行劫持,即可成功控制进程。另外,受到控制的渲染进程会通过IPC调用创建新进程。 有了这些知识,我使用了许多与以前的博客文章相同的技术来开发了完整的POC。USER_RESTRICTED_SAME_ACCESS令牌的更高特权简化了漏洞利用。例如,我们不再需要劫持COM Server的线程,因为特权更高的令牌使我们可以直接打开进程。另外,至关重要的是,我们永远不需要离开“受限沙箱”,因此该漏洞利用程序不必依赖于先前MS所修复的内核错误版本。您可以找到问题附带的完整POC,并且我在下图中总结了步骤。 开发补丁程序 在我的报告中,我建议了针对此问题的补丁程序,请在沙箱策略中启用SetLockdownDefaultDacl选项。SetLockdownDefaultDacl从默认DACL中同时删除了RESTRICTED和登录SID,这将阻止一个L5进程打开另一个进程。我已经添加了此沙箱策略功能,以响应我在上一个博客中提到的GPU沙箱逃逸,这是Pwn2Own的lokihardt使用的。但是,其目的是阻止GPU进程打开渲染器进程,而不是阻止一个GPU进程打开另一个GPU进程。因此,该策略未在GPU沙箱上设置,而仅在渲染器上设置。 事实证明,我不是第一个报告一个Firefox内容处理程序打开另一个进程的人。 Niklas Baumstark在我报告前一年就已经报告过。我建议的修复SetLockdownDefaultDacl的功能已在修复Niklas的问题报告中进行了尝试,它破坏了包括DirectWrite缓存和音频播放在内的各种功能,会导致显著的性能下降,这会导致使用SetLockdownDefaultDacl成为不可取的事情。上述提到的,诸如DirectWrite高速缓存中断的原因是由于Windows RPC服务中的编码模式导致的,如下所示: int RpcCall(handle_t handle, LPCWSTR some_value) {
DWORD pid;
I_RpcBindingInqLocalClientPID(handle, &pid);
RpcImpersonateClient(handle);
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, nullptr, pid);
if (!process)
return ERROR_ACCESS_DENIED;
...
}
此示例代码在特权服务中运行,并且由沙盒应用程序通过RPC调用。它首先调用RPC运行时以查询调用者的进程ID。然后,它模拟了调用者并尝试打开调用过程的句柄。如果打开过程失败,则RPC调用将返回拒绝访问错误。 对于正常的应用程序,一个完全合理的假设是调用者可以访问自己的进程。但是,一旦锁定了进程安全级别,情况就不再如此。如果我们要禁止访问同一级别的其他进程,那么结果就是我们也禁止打开自己的进程。通常,这不会导致什么问题,因为流程中的大多数代码都使用“当前进程的”伪句柄,该句柄从未进行访问检查。 Niklas的报告并未包含完整的沙箱逃逸功能。缺少完整的POC加上修复它的困难导致修复停滞。但是,如果使用完整的沙箱逃逸来演示问题的影响,则Mozilla必须在性能或安全性之间进行选择,除非可以采用其他补丁程序。 该补丁程序必须做两件事: 授予进程对其自己的进程和线程的访问权限。
拒绝同一级别的任何其他进程。
没有任何管理员权限,我们无法使用许多东西,例如内核进程回调。该补丁程序必须在普通用户权限的用户模式下运行。 修复漏洞的关键,在于受限制的SIDs列表要包括的SIDs是不在令牌中。我们可以为每个沙盒生成一个随机的SID进程,将其作为受限SID并添加到默认DACL中。然后,我们可以使用SetLockdownDefaultDacl锁定默认DACL。 当打开进程时,访问检查将与当前用户的SID相匹配,以进行常规检查,而随机SID与受限SID检查相匹配。但是,每个内容进程将具有不同的随机SID,因此尽管正常检查仍将通过,但访问检查无法成功通过受限SID的检查。这达成了我们的目标。您可以在PolicyBase :: MakeTokens中查看实现方式。 我将补丁添加到Chromium代码仓库中,Firefox能够对其进行合并和测试。它起到了阻止攻击的作用,并且似乎没有引入以前的性能问题。 该修补程序的另一个问题是确保系统上所有其他进程的安全,这些进程必须采用缓解措施来进行防御,包括所有Chromium浏览器以及Chromium的用户(例如Electron)。例如,如果未更新Chrome,则Firefox内容进程可能会关闭Chrome的GPU进程,这将导致Chrome重新启动它,而firefox进程可能会通过劫持新的GPU进程而通过Chrome逃逸。这就是为什么即使不是直接受到攻击,我还是启用了Chromium GPU进程的缓解措施,该进程已在2020年4月底发布的M83(和Microsoft Edge 83)中提供。 最后,此博客文章演示了Firefox中的沙箱逃逸,同时也需要向Chromium沙箱添加新的防护功能。与以前的博客文章相比,无需更改Windows代码。
戳“阅读原文”查看更多内容
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论