MIT 6.858 计算机系统安全讲义 2014 秋季(一)(4)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
云防火墙,500元 1000GB
访问控制,不限时长
简介: MIT 6.858 计算机系统安全讲义 2014 秋季(一)

MIT 6.858 计算机系统安全讲义 2014 秋季(一)(3)https://developer.aliyun.com/article/1484146

回到 OKWS:他们的应用/动机是什么?

  • 约会网站:担心数据保密性。
  • 不太担心对手闯入并发送垃圾邮件。
  • 大量的服务器端代码执行:匹配,配置文件更新,…
  • 必须在用户之间共享(例如匹配)-- 不能只是分区。
  • 对整体计划的良好总结:
  • “最容易受攻击的方面对攻击者最无用”

为什么这么难?

  • Unix 使降低权限变得棘手(chroot,UID,…)
  • 应用程序需要以复杂的方式共享状态。
  • Unix 和 SQL 数据库没有细粒度的共享控制机制。

OKWS 如何分割 Web 服务器?

  • 论文中的图 1。
  • 这个 Web 服务器中的请求是如何流动的?
  • okd -> oklogd
  • -> pubd
  • -> svc -> dbproxy
  • -> oklogd
  • 这种设计如何映射到物理机器?
  • 可能有许多前端机器(okldokdpubdoklogdsvc
  • 几台 DB 机器(dbproxy,DB)

这些组件如何互动?

  • okld为每个服务设置socketpairs(双向管道)。
  • 一个用于控制 RPC 请求的套接字对(例如,“获取新的日志套接字对”)。
  • 用于日志记录的一个套接字对(okld首先通过 RPC 从oklogd获取它)。
  • 对于 HTTP 服务:一个用于转发 HTTP 连接的套接字对。
  • 对于okd:HTTP 服务的套接字对的服务器端 FD(HTTP+RPC)。
  • okd监听一个单独的套接字以接收控制请求(repubrelaunch)。
  • 在图 1 中似乎是端口 11277,但在 OKWS 代码中是 Unix 域套接字。
  • 对于repubokdpubd通信以生成新模板,
  • 然后通过 RPC 控制通道将生成的模板发送给每个服务。
  • 服务通过 TCP 与 DB 代理通信(通过端口号连接)。

OKWS 如何在图 1 中的组件之间强制隔离?

  • 每个服务作为单独的 UID 和 GID 运行。
  • chroot 用于将每个进程限制在单独的目录中(几乎)。
  • 组件通过管道(或者说 Unix 域套接字对)进行通信。
  • 用于传递 HTTP 连接的文件描述符传递。
  • okld的目的是什么?
  • 为什么okld不同于okd
  • 为什么okld需要以 root 身份运行?(端口 80,chroot/setuid。)
  • okld启动服务需要什么?
  • 创建套接字对
  • 获取新的oklogd套接字
  • forksetuid/setgidexec服务
  • 将控制套接字传递给okd
  • oklogd的目的是什么?
  • pubd的目的是什么?
  • 为什么我们需要数据库代理?
  • 确保每个服务在受损时无法获取其他数据。
  • DB 代理协议由应用程序开发人员定义,取决于应用程序的要求。
  • 一个可能常见的代理类型是模板化的 SQL 查询。
  • 代理强制执行整体查询结构(选择、更新),
  • 但允许客户端填写查询参数。
  • 20 字节令牌是从哪里来的?
  • 作为服务的参数传递。
  • 谁检查令牌?
  • DB 代理有令牌列表(和允许的查询?)。
  • 谁生成令牌?
  • 不清楚;系统管理员手动?
  • 令牌泄露会怎样?
  • 受损组件可能会发出查询。
  • 表 1:为什么所有服务和okld都在同一个 chroot 中?
  • 这是一个问题吗?
  • 我们如何决定?
  • 那里有哪些可读写文件?
  • 可读性:包含服务代码的共享库。
  • 可写:每个服务都可以写入自己的/cores/
  • 配置文件在哪里?/etc/okws_config,由okld保存在内存中。
  • oklogdpubd有单独的 chroots,因为它们具有重要状态:
  • oklogd的 chroot 包含日志文件,希望确保它没有被修改。
  • pubd的 chroot 包含模板,希望避免泄露它们(?)。
  • 为什么 OKWS 需要为每个服务单独的 GID?
  • 需要执行二进制文件,但文件所有权允许 chmod。
  • 解决方案:二进制文件由 root 所有,服务是组所有者,模式 0410。
  • 为什么是 0410(用户读取,组执行),而不是 0510(用户读取和执行)?
  • 为什么不按用户处理?
  • 每个用户是否严格更好?
  • 用户 X 服务?
  • 对于 okcupid 来说,每个服务的隔离可能是有道理的。
  • (即,也许他们需要在用户之间进行大量共享?)
  • 每个用户隔离需要为每个用户分配 UID,使okld变得复杂。
  • 并降低性能(尽管对于某些用例可能仍然可以接受)。

OKWS 是否实现了其目标?

  • OKWS 解决了典型 Web 攻击列表中的哪些攻击,以及如何解决?
  • 除了 XSS 之外的大多数问题都已解决。
  • 通过使用专门的模板例程,XSS 在某种程度上得到解决。
  • 每个组件被损坏的影响是什么,以及“攻击面”是什么?
  • okld:对 Web 服务器机器的根访问权限,但也许没有对数据库的访问权限。
  • 攻击面:很小(除了 svc 退出之外没有用户输入)。
  • okd:拦截/修改所有用户 HTTP 请求/响应,窃取密码。
  • 攻击面:解析 HTTP 请求的第一行;控制请求。
  • pubd:损坏模板,利用可能利用某些服务中的错误?
  • 攻击面:从 okd 获取模板的请求。
  • oklogd:损坏/忽略/删除/伪造日志条目。
  • 攻击面:来自 okd、okld、svcs 的日志消息。
  • service:向用户发送垃圾,访问 svc 的数据(模块化 dbproxy)。
  • 攻击面:来自用户的 HTTP 请求(+来自 okd 的控制消息)。
  • dbproxy:访问/更改其所连接的数据库中的所有用户数据。
  • 攻击面:来自授权服务的请求。
  • 未经授权服务的请求(易于丢弃)。
  • 一旦单个服务被损坏,操作系统内核就成为攻击面的一部分。
  • Linux 内核漏洞很少见,但每年仍然会出现几次。
  • OKWS 假设开发人员在设计层面做正确的事情(也许在实现层面不是):
  • 将 Web 应用程序拆分为单独的服务(而不是全部放在一个服务中)。
  • 为 DB 代理定义精确的协议(否则任何服务都可以获取任何数据)。
  • 性能?
  • 似乎比大多数替代方案更好。
  • 在负载下性能更好(因此在一定程度上抵抗 DoS 攻击)
  • OKWS 与 Apache 相比如何?
  • 总体而言,更好的设计。
  • okld以 root 身份运行,与 Apache 中没有任何东西相比,但可能不重要。
  • 两者都没有很好的解决客户端漏洞(XSS 等)
  • 对手如何试图破坏类似 OKWS 系统?
  • 利用 C++代码中的缓冲区溢出或其他漏洞。
  • 在某个dbproxy中找到 SQL 注入攻击。
  • 在服务代码中找到逻辑错误。
  • 发现跨站脚本漏洞。

OKWS 有多成功?

  • 论文中描述的问题仍然相当普遍。
  • okcupid.com 仍在运行 OKWS,但似乎没有被其他网站使用。
  • C++可能不是编写 Web 应用程序的好选择。
  • 对于许多 Web 应用程序,获得 C++性能可能并不关键。
  • 设计应该适用于其他语言(Python 等)。
  • 实际上,6.858 实验室中的zookws受 OKWS 启发,运行 Python 代码。
  • 对于典型的 Web 应用程序,DB 代理的想法并没有起飞。
  • 但是 DB 代理对于限制服务可以访问的数据至关重要。
  • 为什么?
  • 需要开发人员定义这些 API:额外的工作,会妨碍。
  • 很难提前精确定义允许的 DB 查询。
  • (尽管如果很困难,可能是安全策略模糊的标志。)
  • Apache 的特权分离工作(尽管仍然难以使用)。
  • Unix 使非根用户难以操作用户 ID。
  • 性能是一个问题(为每个请求运行一个单独的进程)。
  • scripts.mit.edu有类似的设计,以不同的 UID 运行脚本。
  • 主要担心将用户相互隔离。
  • 偏执的 Web 应用程序开发人员可以为每个组件创建单独的锁。
  • 敏感系统在更粗粒度上进行分区。
  • 信用卡处理公司将信用卡数据与其他所有数据分开。
  • 使用虚拟机或物理机器隔离来分割应用程序、数据库等。

你如何将现代 Web 应用程序框架与 OKWS 集成?

  • 需要帮助 okd 找出如何将请求路由到服务。
  • 需要实现 DB 代理,或其变体,以保护数据。
  • 取决于应用代码对静态分析的适应性。
  • 或者需要要求程序员为服务注释可以运行的查询。
  • 需要确保应用代码可以在单独的进程中运行(可能没问题)。

参考资料

能力和其他保护机制

注意: 这些讲座笔记是从 2014 年 6.858 课程网站 上发布的笔记稍作修改而来。

混淆的副手问题

"混淆的副手"的作者遇到了什么问题?

  • 他们的系统有一个 Fortran 编译器,/sysx/fort(Unix 文件名语法)
  • 他们希望 Fortran 编译器记录使用统计信息,但在哪里?
  • 创建了一个特殊的统计文件,/sysx/stat
  • 给了/sysx/fort“家庭文件许可证”(类似于关于/sysx 的 setuid)
  • 出了什么问题?
  • 用户可以调用编译器,要求将输出写入/sysx/stat
  • 例如/sysx/fort /my/code.f -o /sysx/stat
  • 编译器打开提供的路径名,并成功,因为它的许可证。
  • 用户本身不能写入那个/sysx/stat文件。
  • 为什么/sysx/fort只是编译器中的一个错误?
  • 原则上,可以通过在各个地方添加检查来解决这个问题。
  • 问题:需要在几乎所有打开文件的地方添加检查。
  • 完全正确的代码一旦成为 setuid 二进制文件的一部分就会变得有 bug。
  • 那么什么是“混淆的副手”?
  • 编译器代表两个主体运行:
  • 用户主体(用于打开用户的文件)
  • 编译器主体(用于打开编译器的文件)
  • 不清楚在任何给定时间应该使用主体权限。

我们能在 Unix 中解决这个混淆的副手问题吗?

  • 假设 gcc 想要在/etc/gcc.stats中保留统计信息
  • 可以有一个特殊的 setuid 程序,只能写入该文件
  • 不太方便:不能像打开其他文件那样简单地打开文件。
  • 如果我们让 gcc 成为某个非根用户(统计文件所有者)的 setuid,会怎样?
  • 难以访问用户的原始文件。
  • 如果 gcc 是 setuid-root?(坏主意,但让我们弄清楚为什么…)
  • 大量潜在的缓冲区溢出可能导致 root 访问权限。
  • 需要在 gcc 可能打开文件的每个地方进行检测。
  • 当 gcc 打开文件时,我们应该执行什么检查?
  • 如果是“内部”文件(例如/etc/gcc.stats),也许不需要检查。
  • 如果是用户提供的文件,需要确保用户可以访问它。
  • 可以查看相关文件的权限。
  • 还需要检查导致该文件的目录的权限。
  • 潜在问题:竞争条件。
  • 如果文件在我们检查和使用之间发生更改会怎么样?
  • 常见的漏洞:攻击者用符号链接替换合法文件
  • 符号链接可能指向,比如/etc/gcc.stats,或/etc/passwd,或…
  • 被称为“检查时间到使用时间”的错误(TOCTTOU)。

对这个问题有几种可能的思考方式:

  1. 环境权限: 进程自动使用的权限是问题所在。任何权限都不应该自动使用。对象的名称也应该是访问它的权限。
  2. 复杂的权限检查: 特权应用程序难以复制。通过简化的检查,特权应用程序可能能够正确检查另一个用户是否应该访问某个对象。

什么是环境权限的例子?

  • Unix 用户 ID,组 ID。
  • 防火墙(IP 地址与访问权限)
  • HTTP cookies(例如,访问 http://gmail.com 这样的 URL)

通过能力给对象命名有什么帮助?

  • 传递文件描述符而不是传递文件名。
  • 除非调用者被授权打开该文件,否则无法传递有效的 FD。

我们能否使用文件描述符解决通过 setuid gcc 设置的问题?

  • 类似:可以使编译器仅通过 FD 传递接受文件。
  • 或者,可以创建一个 setuid 辅助程序,打开/etc/gcc.stats文件,将一个打开的文件描述符传递回我们的编译器进程。
  • 然后,可以继续像处理任何其他文件一样使用这个打开的文件。
  • 如何确保只有 gcc 可以运行这个辅助程序?
  • 使 gcc 设置为某个特殊组的 setgid。
  • 使辅助程序仅对该特殊组可执行。
  • 确保该组没有其他授予的特权。

Capsicum 作者试图通过能力解决什么问题?

  • 在各种应用程序中降低不可信代码的特权。
  • 总体计划:
  • 将应用程序分解为较小的组件。
  • 减少最容易受攻击的组件的特权。
  • 仔细设计接口,以便一个组件无法危害另一个组件。
  • 为什么这么困难?
  • 在传统的 Unix 系统中难以降低代码的特权(“沙盒”)。
  • 难以为沙盒化代码提供有限的访问权限(对文件、网络等)。

什么样的应用程序可能会使用沙盒化?

OKWS

  • 处理网络输入的程序:
  • 将输入处理代码放入沙盒中。
  • 复杂操作数据的程序:(gzip,Chromium,媒体编解码器,浏览器插件,…)
  • 将复杂(且可能有错误)的部分放入沙盒中。
  • 从互联网下载的任意程序怎么样?
  • 稍微不同的问题:需要隔离未修改的应用程序代码。
  • 一个选择:程序员编写他们的应用程序以在沙盒中运行。
  • 在某些情况下有效:Javascript,Java,Native Client,…
  • 需要在沙盒代码上制定一个环境标准。
  • 另一个选择:对现有代码施加新的安全策略。
  • 可能需要保留程序员正在使用的所有 API。
  • 需要对现有 API 施加检查,在那种情况下。
  • 不清楚访问文件、网络等的策略应该是什么。
  • 希望避免被欺骗误用特权的应用程序?
  • 假设两个 Unix 用户,Alice 和 Bob,正在某个项目上工作。
  • 两者都在某个组G中,并且项目dir允许该组访问。
  • 假设 Alice 从项目目录向某人发送一个文件。
  • 风险:Bob 可能用符号链接替换文件为 Alice 的私人文件。
  • Alice 的进程将隐式使用 Alice 的环境特权来打开。
  • 可以将这看作对单个文件操作进行沙盒化。

有哪些沙盒化计划(机制)存在(优势,限制)?

  • 操作系统通常提供某种安全机制(“原语”)。
  • 例如,在 Unix 中的用户/组 ID,正如我们在上一堂课中看到的。
  • 今天,我们将研究操作系统级别的安全原语/机制。
  • 当您关心保护操作系统管理的资源时通常是一个很好的选择。
  • 例如,文件,进程,粗粒度内存,网络接口等。
  • 许多操作系统级别的沙箱机制在进程级别工作。
  • 适用于可以作为一个单元进行隔离的整个进程。
  • 可能需要重新设计应用程序以创建用于隔离的进程。
  • 其他技术可以提供更细粒度的隔离(例如,在 proc 中的线程)。
  • 语言级别的隔离(例如,Javascript)。
  • 二进制仪器化(例如,Native Client)。
  • 为什么我们需要这些其他的沙箱技术?
  • 更容易控制对非操作系统/更细粒度对象的访问。
  • 或者也许可以以与操作系统无关的方式进行沙箱化。操作系统级别的隔离通常与更细粒度的隔离结合使用。
  • 更细粒度的隔离通常很难做到正确(Javascript,NaCl)。例如,Native Client 同时使用了细粒度沙箱和操作系统级别的沙箱。
  • 将在后续讲座中更详细地讨论这些问题。

计划 0:虚拟化所有内容(例如,VMs)。

  • 在虚拟化环境中运行不可信代码。
  • 许多示例:x86 qemu,FreeBSD jails,Linux LXC,…
  • 几乎是一种不同类别的机制:严格隔离。
  • 优势:VM 内部的沙箱代码几乎与外部没有交互。
  • 优势:可以沙箱未经修改的代码,不期望被隔离。
  • 优势:一些 VM 可以由任意用户启动(例如,qemu)。
  • 优势:通常与其他隔离技术可组合,提供额外层次。
  • 缺点:难以允许一些共享:没有共享进程,管道,文件。
  • 缺点:虚拟化所有内容通常会使 VM 相对较重。
  • 每个沙箱都会带来非常重要的 CPU/内存开销。

计划 1:自主访问控制(DAC)。

  • 每个对象都有一组权限(访问控制列表)。
  • 例如,Unix 文件,Windows 对象。
  • “自主”意味着应用程序在对象上设置权限(例如,chmod)。
  • 每个程序都以某些主体的权限运行。
  • 例如,Unix 用户/组 ID,Windows SIDs。
  • 当程序访问对象时,检查程序的权限以决定。

“环境特权”:每次访问都隐式使用的权限。

Name              Process privileges
     |                       |
     V                       V
   Object -> Permissions -> Allow? 
  • 如何在 DAC 系统上(例如,Unix)沙箱化程序?
  • 必须分配一个新的主体(用户 ID):
  • 否则,现有主体的权限将被隐式使用!
  • 防止进程读取/写入其他文件:
  • 在整个文件系统上更改权限?繁琐,不切实际,需要 root 权限。
  • 即使如此,新程序也可以创建重要的可全球写入文件。
  • 替代方案:chroot(同样,必须是 root)。
  • 允许进程读/写某个文件:
  • 如果可能的话,适当设置文件的权限。
  • 将文件链接/移动到沙箱的chroot目录中?
  • 防止进程访问网络:
  • Unix 中没有真正的答案。
  • 可能配置防火墙?但不是真正针对进程的。
  • 允许进程访问特定的网络连接:
  • 如上所述,在 Unix 中没有很好的计划。
  • 控制沙盒可以杀死 / 调试 / 等的进程:
  • 可以在相同的 UID 下运行,但可能特权太多。
  • 该 UID 也可能具有其他特权…
  • **问题:**在大多数 DAC 系统上,只有 root 可以创建新的主体。
  • 例如,Unix,Windows。
  • **问题:**一些对象可能没有明确可配置的访问控制列表。
  • Unix:进程,网络,…
  • **问题:**文件上的权限可能与沙盒所需的策略不匹配。
  • 可以通过使用chroot对文件进行某种程度的解决,但很麻烦。
  • **相关问题:**使用子特权执行某些操作。
  • 回想一下 Alice 通过电子邮件将文件发送到共享组目录的示例。
  • “混淆副手问题”:程序是多个主体的“副手”。
  • *一个解决方案:*检查组权限是否允许访问(手动,容易出错)。
  • *替代方案:*明确为每个操作指定特权。
  • 权限可以帮助:能力(例如,fd)结合了对象 + 特权。
  • 一些 Unix 功能与纯能力设计不兼容(按名称创建符号链接)。

计划 2:强制访问控制(MAC)。

  • 在 DAC 中,安全策略由应用程序自身设置(chmod 等)。
  • MAC 试图帮助用户/管理员为应用程序指定策略。
  • *“强制”*意味着应用程序无法更改此策略。
  • 传统的 MAC 系统试图强制执行军事机密级别。

*示例:*确保绝密程序无法泄露机密信息。

Name    Operation + caller process
     |               |
     V               V
   Object --------> Allow?
                     ^
                     |
   Policy -----------+ 
  • *注意:*许多系统在其中具有 DAC + MAC 的方面。
  • 例如,Unix 用户 ID 是“DAC”,但可以争论防火墙是“MAC”。
  • 并不重要–了解设计空间中的极端点是很好的。
  • Windows 强制完整性控制(MIC)/ FreeBSD 中的 LOMAC。
  • 为每个进程跟踪“完整性级别”。
  • 文件与其关联的最低完整性级别。
  • 进程无法写入高于其完整性级别的文件。
  • Windows Vista 中的 Internet Explorer 以低完整性运行,无法覆盖系统文件。
  • FreeBSD LOMAC 还跟踪进程读取的数据。
  • (类似于许多基于信息流的系统。)
  • 当进程读取低完整性数据时,它也变得低完整性。
  • 传递性,防止对手间接篡改文件。
  • 对于沙盒化不是立即有用:只有固定数量的级别。
  • SElinux
  • *想法:*系统管理员指定系统范围的安全策略。
  • 策略文件指定是否应允许或拒绝每个操作。
  • 为了帮助决定是否允许/拒绝,文件标记为“类型”。
  • (另一个整数值,与 inode 中的 uid、gid 等一起存储。)
  • Mac OS X 沙盒(“Seatbelt”)和 Linuxseccomp_filter
  • 应用程序为是否允许/拒绝每个系统调用指定策略。
  • (在 MacOSX 的机制中用 LISP 编写,或者在 Linux 中用 BPF 编写。)
  • 根据参数确定系统调用的安全影响可能很困难。
  • 路径名指的是什么?符号链接,硬链接,竞争条件,…
  • (尽管 MacOSX 的沙盒提供了更多信息)
  • 优势: 任何用户都可以对任意代码片段进行沙盒化!
  • 限制: 程序员必须分别编写策略和应用代码。
  • 限制:有些操作只能以粗粒度进行过滤。
  • 例如,在 MacOSX 的过滤语言中的 POSIX shm,根据 Capsicum 论文。
  • 限制:策略语言可能使用起来很尴尬,无状态等。
  • 例如,如果应用程序应该与某个服务器建立精确的一个连接?
  • 注意: seccomp_filter 与常规/旧版 seccomp 有很大不同,而 Capsicum 论文讨论的是常规/旧版 seccomp
  • 将策略与应用代码分离是否是个好主意?
  • 取决于总体目标。
  • 如果用户/管理员想查看或更改策略,可能会很有用。
  • 如果应用程序开发人员需要同时维护代码和策略,这将成为问题。
  • 对应用程序开发人员来说,可能有助于澄清策略。
  • 较少集中的“MAC”系统(Seatbelt、seccomp)提供了一种折衷方案。
  • 待办事项: 还要看看《赛里斯墙安全策略》

计划 3:能力(Capsicum)。

  • 不同的访问控制计划:能力。
  • 如果进程有某个对象的句柄(“能力”),就可以访问它。
  • 能力 --> 对象
  • 没有特权、访问控制列表、策略等的单独问题。
  • 例如:Unix 上的文件描述符是文件的能力。
  • 程序无法制造未经合法获取的文件描述符。
  • 为什么不? 操作系统创建和管理文件描述符。应用程序无法伪造文件描述符。它必须通过漏洞写入操作系统内存。
  • 一旦文件打开,就可以访问它;检查发生在打开时。
  • 可以将打开的文件传递给其他进程。
  • 文件描述符也有助于解决“检查时间与使用时间”(TOCTTOU)漏洞。
  • 能力通常是短暂的:不是磁盘上的 inode 的一部分。
  • 启动程序的任何内容都需要每次重新创建能力。
  • 全局命名空间
  • 为什么这些人如此着迷于消除全局命名空间?
  • 全局命名空间需要一些访问控制策略(例如,环境权限)。
  • 难以控制沙盒对全局命名空间中对象的访问。
  • 内核更改
  • 只是为了再次确认:为什么我们需要内核更改?
  • 我们能否将所有内容都实现在一个库中(并通过 LD_PRELOAD 加载)?
  • 需要操作系统在进入能力模式后拒绝应用程序访问全局命名空间
  • 将更多内容表示为文件描述符:进程(pdfork)。
  • 一般来说是个好主意。
  • 能力模式: 一旦进程进入 cap 模式,就无法离开(包括所有子进程)。
  • 在能力模式下,只能使用文件描述符 – 没有全局命名空间。
  • 不能通过完整路径名打开文件:不需要像 OKWS 中的 chroot
  • 仍然可以通过相对路径名打开文件,给定目录的 fd(openat)。
  • 不能在路径名或符号链接中使用“…”:为什么?
  • 原则上,“…” 可能没问题,只要“…” 不走得太远。
  • 难以正确执行。
  • 假设设计:
  • 禁止在根能力中查找“…”。
  • 路径名中的非“…”组件不得比“…”多,忽略“.”。
  • 假设一个进程对 /foo 拥有能力 C1
  • 在单个进程中的竞争条件,有 2 个线程:

竞争条件示例:

T1: mkdir(C1, "a/b/c")
    T1: C2 = openat(C1, "a")
    T1: C3 = openat(C2, "b/c/../..")   # should return a cap for /foo/a
        Let openat() run until it's about to look up the first ".."
    T2: renameat(C1, "a/b/c", C1, "d")
    T1: Look up the first "..", which goes to "/foo"
        Look up the second "..", which goes to "/" 
  • Unix 权限仍然适用吗?
  • 是的 – 仅因为你对目录有一个 cap,就不能访问目录中的所有文件。
  • 但意图是沙盒不应依赖 Unix 权限。
  • 对于文件描述符,添加一个存储允许操作的包装对象。
  • 内核在哪里检查能力?
  • 内核中的一个函数查找 fd 号码 – 修改它以检查能力。
  • 还修改了查找路径名的 namei 函数。
  • 良好实践: 寻找窄接口,否则容易忽略检查。
  • libcapsicum
  • 应用程序开发人员为什么需要这个库?
  • 最大的功能:在沙盒中启动新进程。
  • fd 列表
  • 主要是将大量文件描述符传递给子进程的便捷方式。
  • 通过字符串命名文件描述符,而不是硬编码的 fd 号码。
  • cap_enter()vslch_start()
  • 使用 exec 而不是 cap_enter 进行沙盒化的优势是什么?
  • 内存中的残留数据:例如 OpenSSL/OpenSSH 中的私钥。
  • 应用程序忘记关闭的残留文件描述符。
  • 论文中的图 7:tcpdumpstdinstdoutstderr 上具有特权。
  • 论文中的图 10:dhclient 具有原始套接字,syslogd 管道,租约文件。
  • 优点:任何进程都可以创建一个新的沙盒。
  • (即使沙盒也可以创建沙盒。)
  • 优点:对资源访问的细粒度控制(如果它们映射到 FD)。
  • 文件、网络套接字、进程。
  • 缺点: 对持久文件访问跟踪的故事较弱。
  • 缺点: 禁止全局命名空间,需要以不同方式编写代码。

替代性的能力设计:纯能力为基础的操作系统(KeyKOS 等)。

  • 内核只提供消息传递服务。
  • 消息传递通道(非常类似文件描述符)是能力。
  • 每个应用程序都必须以能力样式编写。
  • Capsicum 声称更加务实:一些应用程序无需更改。

Linux 能力:解决不同的问题。

  • 尝试将根的特权划分为更细粒度的特权。
  • 由各种能力表示:CAP_KILL, CAP_SETUID, CAP_SYS_CHROOT, …
  • 进程可以以特定能力运行,而不是以 root 的所有特权。
  • 参考:capabilities(7)

在应用程序中使用 Capsicum

  • 计划:确保沙盒化进程不使用路径名或其他全局 NS。
  • 对于可能需要访问的每个目录,提前打开 FD。
  • 要打开文件,请使用从这些目录 FD 开始的openat()
  • … 打开大量文件的程序可能会很麻烦。
  • tcpdump
  • 2 行版本:在打开所有 FD 后只需 cap_enter()
  • 使用 procstat 查看生成的能力。
  • 8 行版本:还限制 stdin/stdout/stderr
  • 为什么?避免读取 stderr 日志,更改终端设置,…
  • dhclient
  • 已经进行了特权分离,使用 Capsicum 来加强沙盒(2 行)。
  • gzip
  • 分叉/执行沙盒化的子进程,通过管道使用 RPC 向其提供数据。
  • 非平凡的更改,主要是为了为 RPC 编组/解组数据:409 行代码。
  • *有趣的错误:*一开始忘记传播压缩级别。
  • Chromium
  • 在其他平台上已经进行了特权分离(但在 FreeBSD 上没有)。
  • ~100 行代码用于为沙盒化进程包装文件描述符。
  • OKWS
  • 家庭作业问题有哪些不同的答案?

Capsicum 是否实现了其目标?

  • 使用起来有多难/容易?
  • 在应用程序中使用 Capsicum 几乎总是需要应用程序更改。
  • (许多应用程序倾向于通过路径名打开文件等。)
  • 一个例外:Unix 管道应用程序(过滤器)只操作 FD。
  • 对通过 FD 处理数据的流式应用程序更容易。
  • 其他隔离需要类似的更改(例如,dhclient,Chromium)。
  • 对于现有应用程序,延迟初始化似乎是一个问题。
  • 没有通用解决方案——要么更改代码,要么早期初始化。
  • 建议的计划:沙盒化并查看哪些地方出问题。
  • 可能会有微妙之处:gzip压缩级别错误。
  • 它提供了哪些安全保证?
  • 提供给应用程序开发人员的保证:沙盒只能在打开的 FD 上操作。
  • 结果取决于应用程序开发人员如何划分应用程序、FD。
  • 用户/管理员无法从 Capsicum 获得任何直接保证。
  • 保证假设 FreeBSD 内核没有错误(大量代码),并且 Capsicum 开发人员捕获了所有通过 FD 而非资源访问的方式。
  • 性能开销是多少?(CPU,内存)
  • 访问文件描述符的轻微开销。
  • 使用fork/exec设置沙盒需要花费O(1msec),非平凡的。
  • 特权分离可能需要 RPC / 消息传递,可能会引起注意。
  • 采用情况?
  • 在 FreeBSD 的内核中,现在默认启用(从 FreeBSD 10 开始)。
  • 少数应用程序已经修改为使用 Capsicum。dhclienttcpdump,自论文撰写以来还有几个。参考
  • Casper 守护程序帮助应用程序执行非能力操作。例如,DNS 查找,查找/etc/passwd中的条目等。参考
  • Capsicum 已经移植到 Linux(但不在上游内核存储库中)。

有哪些应用程序不适合 Capsicum?

  • 需要控制对非内核管理对象的访问的应用程序。
  • 例如:X 服务器状态,DBus,在 Web 浏览器中的 HTTP 来源等。
  • 例如:需要确保 DB 文件格式正确的数据库服务器。
  • Capsicum 将管道视为用户级服务器(例如,X 服务器)的一个能力。
  • 需要从沙盒连接到特定的 TCP/UDP 地址/端口的应用程序。
  • Capsicum 通过仅允许对现有打开的 FD 进行操作来工作。
  • 需要其他机制来控制可以打开哪些 FD。
  • 可能的解决方案:辅助程序可以在能力模式之外运行,根据策略为沙盒化程序打开 TCP/UDP 套接字。

参考

相关文章
|
6月前
|
存储 安全 编译器
MIT 6.858 计算机系统安全讲义 2014 秋季(一)(2)
MIT 6.858 计算机系统安全讲义 2014 秋季(一)
110 3
|
6月前
|
存储 传感器 缓存
MIT 6.858 计算机系统安全讲义 2014 秋季(二)(3)
MIT 6.858 计算机系统安全讲义 2014 秋季(二)
70 2
|
6月前
|
JavaScript 安全 前端开发
MIT 6.858 计算机系统安全讲义 2014 秋季(二)(1)
MIT 6.858 计算机系统安全讲义 2014 秋季(二)
111 2
|
6月前
|
安全 Unix Shell
MIT 6.858 计算机系统安全讲义 2014 秋季(一)(3)
MIT 6.858 计算机系统安全讲义 2014 秋季(一)
76 2
|
6月前
|
安全 Java 程序员
MIT 6.858 计算机系统安全讲义 2014 秋季(一)(1)
MIT 6.858 计算机系统安全讲义 2014 秋季(一)
77 2
|
6月前
|
传感器 Web App开发 安全
MIT 6.858 计算机系统安全讲义 2014 秋季(四)(2)
MIT 6.858 计算机系统安全讲义 2014 秋季(四)
61 1
|
6月前
|
存储 缓存 安全
MIT 6.858 计算机系统安全讲义 2014 秋季(四)(1)
MIT 6.858 计算机系统安全讲义 2014 秋季(四)
43 0
|
6月前
|
存储 安全 Linux
MIT 6.858 计算机系统安全讲义 2014 秋季(三)(4)
MIT 6.858 计算机系统安全讲义 2014 秋季(三)
84 0
|
6月前
|
存储 Web App开发 网络协议
MIT 6.858 计算机系统安全讲义 2014 秋季(三)(3)
MIT 6.858 计算机系统安全讲义 2014 秋季(三)
62 0
|
6月前
|
存储 缓存 安全
MIT 6.858 计算机系统安全讲义 2014 秋季(三)(2)
MIT 6.858 计算机系统安全讲义 2014 秋季(三)
52 0