剑和沙盒 5 - Sandboxie的技术架构

Sandboxie 是一个操作系统级的应用程序沙箱。它严重依赖 Windows 安全模型,通过使用非常受限制的访问令牌(不受信任的完整性、已删除的权限、所有组标记为仅拒绝)运行程序来限制对资源的访问。由于程序无法在这些条件下运行,因此 Sandboxie 会在沙箱进程中挂接数百个函数,并重定向/谎报操作结果,以尝试在不影响安全性的情况下修复兼容性。这里有三个组件参与:

  • SbieDll , SbieSvc- 在沙盒进程中安装用户模式钩子并将请求转发给代理组件(和)的 DLL SbieDrv
  • SbieSvc- 一项非沙盒化运行并充当代理的服务。它接受来自沙盒化进程的各种操作请求,根据安全策略验证这些请求,并阻止、重定向或执行这些请求。
  • SbieDrv- 提供透明文件系统和注册表重定向、跟踪进程创建等的驱动程序。

通常,依赖用户模式钩子对于安全性来说不是一个好主意,但在这里它却很有效,因为沙盒进程实际上有两个选择:

  1. 遵循钩子并使其将请求转发给验证安全策略并阻止危险操作的代理。
  2. 通过直接要求操作系统执行操作来绕过用户模式挂钩,并由于受限令牌而立即获得“访问被拒绝”。

以下是参考的Chrome的沙盒

概述

安全性是 Chromium 最重要​​的目标之一。安全性的关键在于理解:只有充分理解系统在所有可能状态下所有可能输入组合的行为,我们才能真正保护系统。对于像 Chromium 这样庞大而多样化的代码库,推断其所有部分的组合行为几乎是不可能的。沙盒的目标是提供硬性保证,无论输入是什么,一段代码最终可以做什么或不能做什么。

沙盒利用操作系统提供的安全性来允许执行无法对计算机进行持久更改或访问机密信息的代码。沙盒提供的架构和确切保证取决于操作系统。本文档涵盖 Windows 实现以及一般设计。Linux 实现在此处描述,OSX实现在此处描述。

如果您不想阅读整个文档,您可以阅读沙盒常见问题解答。常见问题解答中还介绍了沙盒可以保护和不可以保护的内容。

设计原则

  • 不要重新发明轮子:使用更好的安全模型扩展操作系统内核是很有诱惑力的。不要这样做。让操作系统将其安全性应用于它控制的对象。另一方面,创建具有自定义安全模型的应用程序级对象(抽象)是可以的。
  • 最小权限原则:这应该既适用于沙盒代码,也适用于控制沙盒的代码。换句话说,即使用户无法升级为超级用户,沙盒也应该能够正常工作。
  • 假设沙盒代码是恶意代码:出于威胁建模的目的,我们认为一旦执行路径到达函数中的几个早期调用,沙盒就会受到破坏(即运行恶意代码)main()。实际上,这可能发生在接受第一个外部输入时,或者在进入主循环之前。
  • 灵活:非恶意代码不会尝试访问它无法获得的资源。在这种情况下,沙盒应该几乎不会对性能产生影响。当需要以受控方式接触敏感资源一次时,在特殊情况下可以有性能损失。如果操作系统安全性使用得当,通常就是这种情况。
  • 模拟不是安全:模拟和虚拟机解决方案本身并不提供安全性。沙盒不应依赖代码模拟、代码转换或修补来提供安全性。

沙盒Windows架构

Windows 沙盒是仅限用户模式的沙盒。没有特殊的内核模式驱动程序,用户无需成为管理员即可使沙盒正常运行。沙盒专为 32 位和 64 位进程而设计,并且已在 Windows 10 的所有 Windows 操作系统版本上进行了测试。

沙盒以进程级粒度运行。任何需要沙盒化的内容都需要存在于单独的进程中。最小沙盒配置有两个进程:一个是特权控制器,称为代理另一个是一个或多个沙盒化进程,称为目标。在整个文档和代码中,这两个术语都具有这种精确的含义。沙盒以静态库的形式提供,必须链接到代理和目标可执行文件。

经纪人流程

在 Chromium 中,代理始终是浏览器进程。广义上讲,代理是沙盒进程活动的特权控制器/监控器。代理进程的职责包括:

  1. 为每个目标进程指定策略
  2. 生成目标进程
  3. 托管沙盒策略引擎服务
  4. 托管沙盒拦截管理器
  5. 托管沙盒 IPC 服务(到目标进程)
  6. 代表目标进程执行策略允许的操作

代理应始终比其生成的所有目标进程存活得更久。沙盒 IPC 是一种低级机制(不同于 Chromium 的 IPC),用于透明地将某些 Windows API 调用从目标转发到代理:这些调用将根据策略进行评估。然后,代理将执行策略允许的调用,并通过相同的 IPC 将结果返回给目标进程。拦截管理器的工作是修补应通过 IPC 转发到代理的 Windows API 调用。

目标进程

在 Chromium 中,渲染器始终是目标进程,除非--no-sandbox已为浏览器进程指定命令行。目标进程托管将在沙盒内运行的所有代码,以及沙盒基础设施客户端:

  1. 所有代码均需经过沙盒处理
  2. 沙盒IPC客户端
  3. 沙盒策略引擎客户端
  4. 沙盒拦截

第 2、3 和 4 项是与要进行沙盒处理的代码相链接的沙盒库的一部分。

拦截(也称为钩子)是 Windows API 调用通过沙箱 IPC 转发到代理的方式。代理可以重新发出 API 调用并返回结果或直接使调用失败。拦截 + IPC 机制不提供安全性;它旨在在沙箱内的代码无法修改以应对沙箱限制时提供兼容性。为了节省不必要的 IPC,在进行 IPC 调用之前还会在目标进程中评估策略,尽管这并不是作为安全保障,而只是一种速度优化。

预计未来大多数插件将在目标进程内运行。

沙盒限制

沙盒的核心依赖于四种 Windows 机制提供的保护:

  • 受限制的代币
  • Windows作业对象
  • Windows桌面对象
  • 完整性级别

这些机制对于保护操作系统、其配置以及用户数据非常有效,但前提是:

  • 所有可保护资源都具有优于空的安全描述符。换句话说,不存在安全配置错误的关键资源。
  • 计算机尚未受到恶意软件的攻击。
  • 第三方软件不会削弱系统的安全性。

** 请注意,超出此基础/核心的额外缓解措施将在下面的“流程缓解措施”部分中描述。

代币

其他类似沙盒项目面临的一个问题是,在保证进程正常运行的情况下,令牌和作业可以受到多大程度的限制。对于 Chromium 沙盒,最严格的令牌采用以下形式:

常规团体
  • 登录 SID:必填
  • 所有其他 SID:仅拒绝、强制
受限群组
  • S-1-0-0 :强制性
特权
  • 没有任何
正直
  • 不受信任的完整性级别标签(S-1-16-0x0)

由于上述注意事项,几乎不可能找到操作系统将使用此类令牌授予访问权限的现有资源。只要磁盘根目录具有非零安全性,即使是具有零安全性的文件也无法访问。Chromium 渲染器使用此令牌运行,这意味着渲染器进程使用的几乎所有资源都已被浏览器获取,并且它们的句柄已复制到渲染器进程中。

请注意,该令牌不是从匿名令牌或来宾令牌派生而来的;它从用户令牌派生而来,因此与用户登录相关联。因此,系统或域中现有的任何审核仍可使用。

根据设计,沙盒令牌无法保护不安全的资源,例如:

  • 已挂载的 FAT 或 FAT32 卷:这些卷上的安全描述符实际上为空。只要目标中运行的恶意软件能够猜测或推断出这些卷的路径,它就可以读取和写入这些卷。
  • TCP/IP:Windows 2000 和 Windows XP(Vista 除外)中的 TCP/IP 套接字安全性实际上为零。目标中的恶意代码可能会向任何主机发送和接收网络数据包。
  • 一些未标记的对象,例如匿名共享内存部分(例如bug 338538

有关详细信息,请参阅 NULL DACL 和其他危险 ACE 类型、安全编码技术,195-199。

Job 对象

目标进程也在 Job 对象下运行。使用这种 Windows 机制,可以强制执行一些有趣的全局限制,这些限制没有与之关联的传统对象或安全描述符:

  • 禁止使用系统范围的更改SystemParametersInfo(),可用于交换鼠标按钮或设置屏幕保护程序超时
  • 禁止创建或切换桌面
  • 禁止更改每个用户的显示配置,例如分辨率和主显示器
  • 无法读取或写入剪贴板
  • 禁止 Windows 消息广播
  • 禁止设置全局 Windows 钩子(使用SetWindowsHookEx()
  • 禁止访问全局原子表
  • 禁止访问在 Job 对象之外创建的用户句柄
  • 一个活动进程限制(不允许创建子进程)

Chromium 渲染器通常会在所有这些限制处于活动状态的情况下运行。每个渲染器都在其自己的 Job 对象中运行。使用 Job 对象,沙盒可以(但目前不能)阻止:

  • 过度使用 CPU 周期
  • 过度使用内存
  • 过度使用 IO

关于Windows作业对象的更多信息可以在这里找到。

替代桌面

令牌和作业对象定义了一个安全边界:也就是说,具有相同令牌和相同作业对象的所有进程实际上都处于相同的安全上下文中。然而,一个不太为人所知的事实是,在同一桌面上有窗口的应用程序实际上也处于相同的安全上下文中,因为窗口消息的发送和接收不受任何安全检查。不允许跨桌面发送消息。这是臭名昭著的“粉碎”攻击的根源,这就是为什么服务不应该在交互式桌面上托管窗口的原因。Windows 桌面是一个常规内核对象,可以创建并分配安全描述符。

在标准的 Windows 安装中,至少有两个桌面连接到交互式窗口站:常规(默认)桌面和登录桌面。沙盒会创建第三个桌面,该桌面与所有目标进程相关联。此桌面永远不会可见或交互,并有效地隔离了沙盒进程,使其无法窥探用户的交互,也无法向在更高权限上下文中运行的窗口发送消息。

备用桌面的唯一缺点是它使用来自单独池的大约 4MB RAM,在 Vista 上可能更多。

有关窗口站的更多信息

完整性级别

完整性级别在 Windows Vista 及更高版本中可用。它们并不严格定义安全边界,但它们确实提供了一种强制访问控制 (MAC) 形式,并充当 Microsoft 的 Internet Explorer 沙盒的基础。

完整性级别是作为一组特殊的 SID 和 ACL 条目实现的,代表五个递增的权限级别:不受信任、低、中、高、系统。如果对象的完整性级别高于请求令牌,则对对象的访问可能会受到限制。完整性级别还实现了用户界面权限隔离,它将完整性级别的规则应用于同一桌面上不同进程之间交换的窗口消息。

默认情况下,令牌可以读取更高完整性级别的对象,但不能写入。大多数桌面应用程序以中等完整性 (MI) 运行,而 Internet Explorer 的保护模式和我们的 GPU 沙盒等不太受信任的进程以低完整性 (LI) 运行,而我们的渲染器进程则以最低的不受信任完整性级别运行。

低完整性级别令牌只能访问以下共享资源:

  • 对大多数文件具有读取权限
  • 写权限%USER PROFILE%\AppData\LocalLow
  • 对大部分注册表的读取权限
  • 写权限HKEY_CURRENT_USER\Software\AppDataLow
  • 剪贴板(某些格式可复制粘贴)
  • 远程过程调用 (RPC)
  • TCP/IP 套接字
  • 通过以下方式公开窗口消息ChangeWindowMessageFilter
  • 通过 LI(低完整性)标签公开的共享内存
  • 具有 LI(低完整性)启动激活权限的 COM 接口
  • 通过 LI(低完整性)标签公开的命名管道

而不受信任的完整性级别只能写入具有空 DACL 或明确不受信任的强制级别的资源。

您会注意到,前面描述的令牌、作业对象和备用桌面的属性更加严格,实际上会阻止对上述列表中允许的所有内容的访问。因此,完整性级别与其他措施相比有点多余,但它可以看作是额外的纵深防御程度,其使用对性能或资源使用没有明显影响。

随着功能被拆分成更小的服务,不同 Chrome 组件的完整性级别将随时间而变化。在 M75 中,浏览器、崩溃处理程序和网络实用程序进程的完整性级别为“中等”,GPU 进程的完整性级别为“低”,其余大多数服务(包括独立渲染器)的完整性级别为“不受信任”。

有关完整性级别的更多信息可以在这里《Windows Internals》第 1 部分第 7 版的第 7 章中找到。

流程缓解政策

大多数进程缓解策略都可以通过 SetProcessMitigationPolicy 应用于目标进程。沙盒使用此 API 在目标进程上设置各种策略以强制执行安全特性。

重新定位图像:
  • >= Win8
  • 正在处理的所有图像上的地址加载随机化 (ASLR)(并且必须由所有图像支持)。
堆终止:
  • >= Win8
  • 当 Windows 堆损坏时终止该进程。
自下而上的 ASLR:
  • >= Win8
  • 将随机下限设置为进程的最小用户地址。
高熵 ASLR:
  • >= Win8
  • 将自下而上的 ASLR 随机性范围增加到 1TB。
严格句柄检查:
  • >= Win8
  • 立即对错误句柄引用引发异常。
Win32k.sys锁定:
  • >= Win8
  • ProcessSystemCallDisablePolicy,它允许选择性地禁用目标进程可用的系统调用。
  • 渲染器进程现在已将此设置为,这意味着不再允许DisallowWin32kSystemCalls由 提供服务的用户模式调用。这大大减少了渲染器可用的内核攻击面。有关更多详细信息,请参阅此处。win32k.sys
禁用扩展点(旧式挂钩):
  • >= Win8
  • ProcessExtensionPointDisablePolicy
  • 以下注射载体被阻断:
    • AppInit DLL Winsock 分层服务提供商 (LSP)
    • 全局窗口钩子(非线程目标钩子)
    • 传统输入法编辑器 (IME)
控制流保护 (CFG):
  • >= Win8.1 更新 3(KB3000850)
  • 在所有 chrome.exe 进程中启用。未编译到所有 chrome 二进制文件中。
  • 在我们的流程中利用 Microsoft 系统 DLL 中的 CFG 安全性。
  • 编译器/链接器选择,而不是运行时策略选择。请参阅MSDN
CET 影子堆栈:
  • 可在 Windows 10 2004 年 12 月更新中使用。
  • 渲染器中未启用。请参阅票证、MSDN。
禁用字体加载:
  • >=Win10
  • ProcessFontDisablePolicy
禁用无符号代码(CIG)的加载:
  • >= Win10 TH2
  • ProcessSignaturePolicy
  • 防止将未签名的代码加载到我们的进程中。这意味着攻击者在获得执行权后不能仅仅 LoadLibrary DLL(由于其他沙盒缓解措施,这无论如何都不可能),但更重要的是,防止第三方 DLL 被注入到我们的进程中,这会影响稳定性和我们启用其他安全缓解措施的能力。
  • 为所有沙盒子进程启用(启动后)。
  • 已为沙盒渲染器进程启用(预启动)。这消除了进程启动时间差距,而在此过程中可能会发生将未正确签名的 DLL 本地注入渲染器进程的情况。
  • 有关此缓解措施的更多背景信息请参阅msedgedev 博客。
禁用从远程设备加载图像:
  • >= Win10 TH2
  • ProcessImageLoadPolicy
  • 例如网络资源的 UNC 路径。
禁用“强制低”(低完整性级别)的图像加载:
  • >= Win10 TH2
  • ProcessImageLoadPolicy
  • 例如临时 Internet 文件。
额外禁用子进程创建:
  • >= Win10 TH2
  • 若Job level <= JOB_LIMITED_USER,则设置PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICYPROCESS_CREATION_CHILD_PROCESS_RESTRICTEDvia UpdateProcThreadAttribute()
  • 这是一个额外的防御层,因为工作级别可以被打破。另请参阅:票证Project Zero 博客
禁用动态代码 (ACG):
  • >= Windows 10 RS1
  • ProcessDynamicCodePolicy- 也称为任意代码保护 (ACG)。
  • 启用 ACG 后,Windows 内核会强制所有代码页都是不可变的,并且无法创建新的未签名代码页,从而阻止进程在内存中创建和修改代码页。这将导致尝试修改或注入这些进程的代码失败,例如某些破坏浏览器内存的尝试以及某些第三方 DLL。
  • 此功能对于沙盒服务实用程序进程以及不执行 JIT(即时)编译的沙盒渲染器进程默认启用,并且可以通过该BrowserDynamicCodeDisabled功能为浏览器进程启用。

应用程序容器(低盒令牌):

  • 在 Windows 中,这是在内核级别通过 Low Box 令牌实现的,该令牌是普通令牌的精简版本,具有有限的权限(通常只有SeChangeNotifyPrivilegeSeIncreaseWorkingSetPrivilege),在低完整性级别运行,并具有一组“功能”,可以映射以允许/拒绝进程可以执行的操作(有关高级描述,请参阅MSDNINTERNET_CLIENT )。从沙盒角度来看,最有趣的功能是拒绝访问网络,事实证明,如果令牌是 Low Box 令牌并且不存在功能,则会强制执行网络检查。
  • 因此,沙盒采用现有的受限令牌并添加 Low Box 属性,而不授予任何功能,从而获得沙盒进程无法进行网络访问的额外保护。

低权限应用容器 (LPAC)

  • 低特权应用容器 (LPAC) 是应用容器 (见上文) 的扩展,可用于 Windows 10 的更高版本 (RS2 及更高版本),它以比普通应用容器更低的特权级别运行,默认情况下仅向标有ALL RESTRICTED APPLICATION PACKAGES或特定程序包 SID 的内核、文件系统和注册表对象授予访问权限。这与使用 的应用容器相反ALL APPLICATION PACKAGES
  • LPAC 的一个关键特性是可以添加特定的命名功能,例如基于众所周知的 SID(在 中定义base/win/sid.h)的功能或通过调用DeriveCapabilitySidsFromName解析的“命名功能”,这些功能实际上并没有在任何地方严格定义,但可以在各个地方找到,包括以下功能:
    • lpacCom
    • registryRead
    • lpacWebPlatform
    • lpacClipboard
    • ETC...
    • 每个 LPAC 进程都可以为其创建一个特定于进程的 SID,这可用于保护特定于该特定沙箱的文件,并且根据在不同沙箱中运行的服务之间的交互,可以存在多个不同的重叠访问权限集。
LPAC 文件系统权限
  • 重要的是,LPAC 进程在其生命周期内将访问的文件系统和注册表中的所有位置都需要具有正确的 ACL。registryRead对于注册表读取访问很重要,并且 Windows 系统文件ALL RESTRICTED APPLICATION PACKAGES上已经有 ACE,但是沙盒进程需要访问的其他文件(包括二进制文件(例如 chrome.exe、chrome.dll))以及任何数据文件都需要设置 ACL。这通常由安装程序完成,并且也会在测试中自动完成。但是,如果要在其他环境中使用 LPAC 沙盒,则需要使用icacls、安装程序或类似工具手动设置这些文件系统权限。可以在中找到可以使用的 ACE 的示例,testing/scripts/common.py但是在高安全性环境中,应该使用更严格的 SID,例如来自安装程序的SID 。

其他注意事项

操作系统可能有漏洞。值得关注的是 Windows API 中的漏洞,这些漏洞允许绕过常规安全检查。如果存在这样的漏洞,恶意软件将能够绕过沙盒限制和代理策略,并可能危害计算机。在 Windows 下,没有切实可行的方法可以阻止沙盒中的代码调用系统服务。

此外,第三方软件(尤其是反恶意软件解决方案)可能会创建新的攻击媒介。最麻烦的是那些为了启用某些(通常是不需要的)功能而注入 dll 的应用程序。这些 dll 也会被注入沙盒进程。在最好的情况下,它们会出现故障,而在最坏的情况下,它们可能会为其他进程或文件系统本身创建后门,从而使特制的恶意软件能够逃离沙盒。

沙盒政策

应用于目标进程的实际限制由策略配置。策略只是代理调用来定义限制和允许的编程接口。四个函数控制限制,大致对应于四种 Windows 机制:

  • TargetPolicy::SetTokenLevel()
  • TargetPolicy::SetJobLevel()
  • TargetPolicy::SetIntegrityLevel()
  • TargetPolicy::SetDesktop()

前三个调用采用整数级别参数,从非常严格到非常宽松;例如,令牌级别有 7 个级别,作业级别有 5 个级别。Chromium 渲染器通常在所有四种机制中以最严格的级别运行。最后,最后一个(桌面)策略是二进制的,只能用于指示目标是否在备用桌面上运行。

这些限制在设计上比较粗略,因为它们会影响目标可以接触的所有可保护资源,但有时需要更细粒度的解决方案。策略接口允许代理指定异常。异常是一种将目标中发出的特定 Windows API 调用代理到代理的方法。代理可以检查参数并按原样重新发出调用,使用不同的参数重新发出调用,或者干脆拒绝调用。要指定异常,只需一个调用:。AddRule目前支持针对不同 Windows 子系统的以下类型的规则:

  • 文件
  • 命名管道
  • 进程创建
  • 註冊
  • 同步对象

每个子系统的规则的具体形式各不相同,但一般来说,规则是根据字符串模式触发的。例如,可能的文件规则是:

添加规则(SUBSYS_FILES,FILES_ALLOW_READONLY,L“c:\\temp\\app_log\\d*.dmp”)

此规则指定如果目标想要打开文件,只要文件与模式表达式匹配,就会授予访问权限,以进行只读访问;例如,c:\temp\app_log\domino.dmp是满足模式的文件。请参阅头文件以获取受支持对象和受支持操作的最新列表。

规则只能在每个目标进程生成之前添加,并且在目标运行时不能修改,但不同的目标可以有不同的规则。

诊断

在 Chromium 中,可以在chrome://sandbox查看与活动进程相关的策略。类别的跟踪sandbox将输出启动进程时使用的策略。可以使用chrome://tracing或使用--trace-startup=-*,disabled-by-default-sandbox命令行标志启用跟踪。可以使用 调查跟踪输出//tools/win/trace-sandbox-viewer.py

目标引导

目标不会按照策略指定的限制开始执行。它们使用与常规用户进程拥有的令牌非常接近的令牌开始执行。原因是在进程引导期间,操作系统加载程序会访问大量资源,其中大多数资源实际上没有记录,并且随时可能发生变化。此外,大多数应用程序使用标准开发工具提供的标准 CRT;在进程引导后,CRT 也需要初始化,而且 CRT 初始化的内部细节同样没有记录。

因此,在引导阶段,进程实际上使用两个令牌:锁定令牌(即原有的进程令牌)和初始令牌(设置为初始线程的模拟令牌)。实际上实际SetTokenLevel定义是:

SetTokenLevel(TokenLevel 初始,TokenLevel 锁定)

完成所有关键初始化后,执行继续在main()或 处WinMain(),此时两个令牌仍处于活动状态,但只有初始线程可以使用功能更强大的初始令牌。目标有责任在准备就绪时丢弃初始令牌。这可以通过一次调用完成:

下标()

目标发出此调用后,唯一可用的令牌是锁定令牌,并且完整的沙盒限制将生效。此调​​用的效果无法撤消。请注意,初始令牌是仅对主线程有效的模拟令牌,在目标进程中创建的其他线程仅使用锁定令牌,因此不应尝试获取任何受安全检查的系统资源。

目标以特权令牌开始的事实简化了显式策略,因为在进程启动时需要完成一次的任何特权操作都可以在调用之前完成,LowerToken()并且不需要在策略中制定规则。

重要的

确保在调用 LowerToken() 之前关闭使用初始令牌获取的所有敏感操作系统句柄。任何泄露的句柄都可能被恶意软件滥用以逃离沙盒。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拉达曼迪斯II

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值