文件系统和文件 API 安全性缺失指南
要确定攻击者是否能够读取 ours/secret 文件的内容,我们可以逐步分析以下情况:
文件创建和所有权:
一个以 root 身份运行的系统守护进程创建了 ours/secret 文件,文件所有权为 root:wheel,权限为 rwx------(700)。这意味着只有 root 用户可以读取、写入和执行这个文件。
POSIX ACL:
为攻击者应用了 POSIX "read" 扩展 ACL(访问控制列表)。这通常允许攻击者读取文件,尽管文件的权限设置为不允许。
扩展属性:
系统为文件添加了扩展属性 com.apple.quarantine。这个属性用于标记从互联网下载的文件,但它不会影响文件的权限或 ACL。
守护进程写入内容:
守护进程向 ours/secret 文件中写入了内容。
基于这些点:
权限:文件权限 rwx------ 限制了只有 root 用户可以访问该文件。
ACL:如果 ACL 允许攻击者读取,那么尽管文件的标准 UNIX 权限不允许,攻击者还是能够读取该文件。
扩展属性:com.apple.quarantine 属性不会影响访问控制或权限。
结论:
如果 POSIX "read" 扩展 ACL 确实赋予了攻击者读取权限,那么攻击者可以读取 ours/secret 的内容。ACL 的设置会覆盖默认的文件权限,只要 ACL 允许读取,攻击者就能够访问文件内容。
让我们逐一解答这些问题,以帮助更全面地理解情况:
-
挂载情况如何?
- 目前我们不清楚 HFS+ 是如何挂载的。这需要检查挂载点和选项。
-
是否启用了
noowners
选项?noowners
选项指的是在挂载文件系统时是否忽略文件的所有者信息。如果启用了该选项,文件的所有者和权限可能不会起作用。你可以通过mount
命令查看挂载选项,或检查系统文档来确认。
-
我们可以开启
noowners
吗?- 如果 HFS+ 文件系统允许,理论上可以通过重新挂载或调整挂载选项来启用
noowners
。具体步骤依赖于系统的配置和权限。
- 如果 HFS+ 文件系统允许,理论上可以通过重新挂载或调整挂载选项来启用
-
我们是否有访问备份镜像的权限?
- 如果 HFS+ 文件系统有备份镜像(如某些虚拟磁盘镜像),你需要确认是否有权限访问这些镜像。通常需要管理员权限来访问或修改镜像。
-
ours
目录上方是否有其他挂载?- 需要检查是否有其他文件系统挂载在
ours
目录上方。这可以通过mount
命令或文件系统工具查看挂载点来确认。
- 需要检查是否有其他文件系统挂载在
-
secret
文件是普通文件,还是一般意义上的“文件”?- 确认
secret
是否是一个常规文件。可能需要检查文件的实际类型和属性,以确定是否是一个真正的文件或仅仅是一个占位符或链接。
- 确认
-
ACL(访问控制列表)情况如何?
- 需要检查文件的 ACL 设置。ACL 可以是允许(allow)或拒绝(deny)。通过
ls -le
或getfacl
命令(在某些系统上)可以查看文件的 ACL 设置。
- 需要检查文件的 ACL 设置。ACL 可以是允许(allow)或拒绝(deny)。通过
-
ACL 是允许还是拒绝?
- 确定 ACL 的类型是允许还是拒绝。ACL 规则决定了对文件的访问权限,允许 ACL 将给予访问权限,而拒绝 ACL 将阻止访问。
-
文件上是否有其他 ACL?
- 确认文件是否有其他的 ACL 设置。这可以通过查看文件的所有 ACL 条目来实现。
-
隔离扩展属性的值是什么?
- 查看文件的
com.apple.quarantine
扩展属性的值。这个属性用于标记文件的来源,如是否从网络下载,并可能影响系统对该文件的处理。
- 查看文件的
回答这些问题将帮助你更好地理解文件的访问控制和安全设置,从而确定攻击者是否能够访问 secret
文件的内容。
在 HFS+ 文件系统上的 macOS 系统中,假设我们有以下情况:
文件创建在攻击者用户拥有的名为 ours 的目录中。
文件由以 root 身份运行的系统守护进程创建。
ours/secret 文件创建时的权限为 root:wheel,权限为 rwx------。
为攻击者创建了 POSIX "read" 扩展 ACL。
系统会添加一个名为 com.apple.quarantine 的扩展属性。
守护进程会向文件中写入内容。
问题是:攻击者是否可以读取 secret 文件的内容?
分析:
文件权限:
rwx------ 权限表示只有文件的所有者(即 root)能够读取、写入和执行文件。
POSIX ACL:
POSIX "read" 扩展 ACL 允许指定用户读取文件。这意味着如果 ACL 设置允许攻击者读取,则攻击者可以绕过默认权限并访问文件内容。
扩展属性:
com.apple.quarantine 扩展属性用于标记文件是否从网络下载,但它不会影响文件的读取权限。
守护进程写入内容:
文件内容由守护进程写入,但这不改变文件的权限设置。
结论:
如果 POSIX "read" 扩展 ACL 设置正确,并且允许攻击者读取 secret 文件,则攻击者可以读取文件的内容。扩展 ACL 可以覆盖默认的文件权限,只要 ACL 赋予了读取权限,攻击者就能够访问文件内容。
这是一个复杂的安全问题,涉及许多细节和潜在的漏洞点。我们逐步解答这些问题:
为什么这个问题不能回答?
挂载情况如何?
HFS+ 如何挂载? 我们不知道 HFS+ 文件系统是如何挂载的,这会影响文件权限和访问控制。
noowners 是否启用? 如果启用了 noowners,文件的所有者和权限可能会被忽略。
我们能否启用 noowners? 需要根据系统的配置来决定。
我们是否有访问备份镜像的权限? 如果有备份镜像,可能会影响访问控制。
ours 上方是否有其他挂载? 需要检查是否有其他文件系统挂载在 ours 目录上方。
secret 文件是什么类型?
secret 是普通文件还是一般意义上的“文件”? 需要确认文件的实际类型。
ACL(访问控制列表)情况如何?
ACL 是允许还是拒绝? 需要确定 ACL 是允许访问还是拒绝访问。
文件上是否有其他 ACL? 可能存在多个 ACL 条目。
隔离扩展属性的值是什么?
com.apple.quarantine 扩展属性的值是什么? 这可能影响文件的处理,但不影响访问权限。
如何创建 secret?
secret 的创建方式如何?
路径是否由我们控制,还是固定的? 需要知道文件路径是否可控。
open() 是否跟随符号链接? 符号链接可能导致意外的文件访问。
是否调用了 open()? 需要确认文件是否由 open() 创建。
umask 是否被尊重? umask 可能影响文件的默认权限。
谁设置了权限?(是否有 chmod() 调用?) 需要确认是否有 chmod() 调用来设置文件权限。
文件创建和 ACL 应用之间是否有竞争? 文件创建和 ACL 应用之间可能存在时间竞争条件。
扩展属性(隔离标志)应用之间是否有竞争? 需要确认是否存在竞争条件。
谁设置了扩展属性? 系统设置扩展属性,可能有安全影响。
write() 是否安全?
write() 是否安全?
write() 是否写入了刚打开的文件? 需要确认是否存在 creat()/open() 竞态条件。
是否可以使用 sudo? 使用 sudo 可能绕过一些安全限制,但需要具体情况具体分析。
macOS 是否有 SIP 规则防止攻击者?
是否有 SIP(System Integrity Protection)规则防止攻击者? SIP 规则可能会限制一些系统操作,但不能完全解决所有问题。
安全研究和开发者问题
文件操作非常难以正确处理:文件操作的复杂性使得安全研究和开发非常困难。
如果我们(安全研究人员)无法推理这些问题,普通开发者如何处理? 这是一个重大问题,表明需要更多的工具和方法来帮助理解和处理文件操作的安全性。
基本知识回顾
POSIX 标准文件权限(rwxrwxrwx)
POSIX 文件 API(open、read、chmod、unlink、mkdir、rename 等)
文件系统对象类型(文件 / 目录 / 符号链接 / 硬链接)
理解这些基本知识有助于更好地分析和解决文件系统安全问题。
POSIX 标准文件权限
-
POSIX 标准文件权限(
rwxrwxrwx
):- 这些权限用于定义文件的读取(r)、写入(w)和执行(x)权限,适用于文件所有者、文件所属组和其他用户。
- 例子:
rwxrwxrwx
表示所有用户都有读取、写入和执行权限。rwx------
表示只有文件所有者有权限,其他用户没有任何权限。
-
需要注意的内容:
- SUID (Set User ID): 使得程序以文件所有者的权限运行。
- SGID (Set Group ID): 使得程序以文件所属组的权限运行,对目录而言,还会继承目录的组所有权。
- Sticky Bit: 使得只有文件所有者才能删除该文件,通常用于
/tmp
目录中。
POSIX 文件 API
-
主要 API:
open()
: 打开文件。read()
: 从文件中读取数据。chmod()
: 修改文件权限。unlink()
: 删除文件。mkdir()
: 创建目录。rename()
: 重命名文件或目录。
-
标准:
- 定义在 IEEE Std 1003.1-2024 中。
- POSIX 标准文档
-
扩展:
- 有些操作系统添加了额外的系统调用,例如:
renameat2()
在 Linux 中。renameatx_np()
在 macOS 中。
- 有些操作系统添加了额外的系统调用,例如:
-
特性:
- 防止路径中任何位置的符号链接(symlink)。
- 原子交换文件 inode。
- 有时 POSIX 标准系统调用会接受额外的非 POSIX 标志,比如 Linux 中的
O_DIRECT
。
-
缺陷:
rename(src, dst)
: 无法阻止符号链接被跟随。open()
的O_NOFOLLOW
: 只防止解析路径的最后一部分。
高级文件系统知识
-
POSIX 扩展 ACL:
- 允许更细粒度的权限控制。
- 可以设置允许或拒绝权限。
- 实现因操作系统而异,Linux ACL 和 BSD/macOS ACL 不同,影响了可移植性。
-
文件系统对象类型:
- 文件(regular file)、目录(directory)、符号链接(symlink)、FIFO(管道)、块设备(block device)、字符设备(character device)。
-
文件系统内部结构:
- 对文件系统的内部工作原理有深入了解是很重要的。
-
文件系统扩展属性:
- IEEE 1003.1e 草案 17: 一个被撤销的 POSIX 标准,但仍被实现。
- 扩展 ACL:
- 在 macOS 上可以使用
file_inherit T
来继承目录的 ACL。 - 扩展 ACL 使得在文件移动时,权限设置也会随之变化。
- 扩展 ACL 是一种“隐蔽”的权限控制方式,不会通过传统 POSIX 调用如
stat()
显示。
- 在 macOS 上可以使用
总结
-
文件操作的复杂性:
- 文件操作非常复杂,涉及权限控制、文件系统类型和文件系统内部结构。
- 对于安全研究人员和开发者而言,理解这些细节至关重要,以避免潜在的安全漏洞。
-
开发者和安全研究人员的挑战:
- 文件操作的安全性需要深入理解操作系统和文件系统的内部实现。
- 对于具有高可移植性的 API 和安全特性的开发,理解这些内容是非常必要的。
硬链接(Hardlinks)
-
概念:
- 硬链接是在同一个文件系统内使用不同的名称引用同一个文件。它们不能跨文件系统(与符号链接不同)。
- 硬链接并不是文件的克隆,而是同一个文件在不同路径下的两个视角。
- 多个硬链接可以指向一个 inode,但通常不能用于目录。
-
目录中的硬链接:
- “..” 是指向父目录的硬链接。
- 目录中的硬链接:
- 例如
/a/b T b
在目录a
中是指向b
的硬链接。
- 例如
- 在理论上,目录间的实际硬链接(例如
./x/a/
和./x/b/
之间)是严格禁止的。
三层攻击面
-
API 层:
- 用户空间应用程序中的漏洞。
- 例如:
open()
的不安全实现。
-
VFS 层:
- 内核中的漏洞。
- 例如:VFS 移除目录时,即使
unlink()
被调用,也可能发生错误。
-
FS 层:
- 用户空间或内核空间(取决于 FS 驱动程序的运行位置)。
- 例如:FAT32 驱动程序可能在竞争条件下不必要地返回错误。
POSIX 兼容性
-
兼容性问题:
- Linux、FreeBSD 和 macOS 都不是完全 POSIX 兼容。
- 虽然非常接近,但某些 POSIX 标准未被完全实现或有不同的实现。
-
POSIX 的定义:
- 在实际应用中,通常指的是 Windows 以外的所有系统。
- WSL(Windows Subsystem for Linux)并不完全符合 POSIX 标准。
VFS(虚拟文件系统)
-
功能:
- VFS 充当用户和底层文件系统驱动程序之间的翻译层。
- 处理缓存、全局文件系统魔法(如 union mounts、资源叉、AppleDouble 处理、firmlinks 等)。
-
翻译问题:
- 并非所有文件系统都支持 VFS 需要的所有功能。
- 例如:macOS 在
rmdir()
时会从空目录中清除 AppleDouble 文件,这在文件系统支持扩展属性时可能导致 ENOTEMPTY 错误。
FS 驱动程序攻击面
-
漏洞:
- 文件系统驱动程序的代码往往较旧、不够智能或有问题。
- 例如:在 macOS 上,FAT32 卷上的符号链接被“模拟”成具有特殊大小和内容的普通文件。
-
攻击向量:
- 文件系统驱动程序常常被设计为处理复杂的文件格式,因此容易受到恶意图像的攻击。
- 可能创建不可能的结构,如硬链接目录、无限目录循环、具有 2 个硬链接但链接计数为 1 的文件等。
路径解析和竞争条件
-
路径类型:
- 绝对路径(如
/etc/passwd
)和 相对路径(如./hello.txt
)。
- 绝对路径(如
-
路径解析:
- 文件系统的视图可能是过时的,因此路径解析可能会出现意外结果。
-
竞争条件示例:
- 当文件系统视图在不同进程间不一致时,可能会出现竞争条件。
- 例如,移动目录时,路径解析可能会失败,导致意外的文件访问。
POSIX 文件系统 API 的限制
-
并发访问:
- POSIX 文件系统 API 并未设计为处理并发访问,尤其是在权限边界跨越时。
-
API 选择问题:
open()
的O_NOFOLLOW
只防止解析路径的最后一个组件。rename()
总是跟随符号链接(尽管情况复杂)。
总结
-
硬链接和文件系统复杂性:
- 硬链接的使用和文件系统的设计有时会导致安全问题和复杂的攻击面。
- 对于安全研究人员和开发者,理解文件系统的内部机制和潜在漏洞是至关重要的。
-
VFS 和 FS 驱动程序:
- VFS 和 FS 驱动程序的设计和实现可能会引入复杂的攻击向量,需要特别关注。
-
路径解析和竞争条件:
- 路径解析和文件系统视图的变化可能导致意外结果,需要谨慎处理并发操作。
访问(access())/打开(open())竞争条件
-
经典的 TOCTOU(检查时机与使用时机):
- 这是最经典的时间检查与使用时间竞争条件(TOCTOU),其难以完全保护。
- 硬链接和符号链接可能使这一问题更复杂。
-
没有 copy() 系统调用:
- 每个程序必须实现自己的文件复制例程,通常实现得不好。
-
没有递归 unlink() 或 rmdir():
- 手动实现这些功能非常困难,容易出错。
- 这通常由库提供,以避免重复代码。
-
符号链接(symlinks)和临时文件(tempfiles):
- 符号链接和临时文件处理不当可能引发问题。
- 文件描述符名称(如 stderr)被硬编码,可能导致隐蔽的安全问题。
文件系统扩展属性
-
扩展属性(Extended Attributes):
- 大多数文件系统支持额外的内容,例如扩展属性和特殊挂载标志。
- 例如:
- ext2/3/4: 支持 append-only、immutable、undeletable 文件,覆盖所有权限检查。
- HFS+: 支持属性、资源叉、压缩等。
-
macOS 的资源叉:
- macOS 的资源叉处理非常复杂。例如:
$ rm a $ echo hi > a $ echo wat > a/..namedfork/rsrc $ cat a/..namedfork/rsrc wat
- 这使得路径查找变得更加复杂。
- macOS 的资源叉处理非常复杂。例如:
特殊路径标记和挂载点
-
路径标记:
- 特殊标记(如 “..” 和 “/”)的含义不一致会导致多重解释。
- 例如:
./a/..namedfork/rsrc
在 macOS 中表示文件a
的资源叉。
-
挂载点:
- 可以移动挂载点,如果能重命名它们的父目录。
- 同一个磁盘可以多次挂载(Linux 支持,但 macOS 不支持)。
-
联合(union)和覆盖(overlay)挂载:
- 在 macOS 和 Linux 中,联合挂载和覆盖挂载允许在文件未找到时查找其他文件系统。
macOS 的特性和漏洞
-
特殊文件系统行为:
.vol/
支持通过 fsid 和 inodenum 访问文件:$ stat /etc/passwd 16777225 40077649 -rw-r--r-- 1 root wheel ... $ stat /.vol/16777225/40077649 16777225 40077649 -rw-r--r-- 1 root wheel ...
-
挂载和文件系统属性:
- AppleSingle/AppleDouble 文件:只有 AppleDouble 相关。
- 文件系统不支持 xattrs 时,macOS 会模拟这些属性。
文件系统漏洞和建议
-
文件系统驱动程序的攻击面:
- 文件系统驱动程序常常对恶意图像非常敏感,因为它们大多只是复杂的文件格式解析器。
-
用户提供的名称到内核表示的 inode 的处理:
- 两种路径类型:绝对路径和相对路径。路径解析可能非常直观,且路径的实际视图可能过时。
学习资源
-
手册页(man pages):
- 使用
man ls
是了解这些内容的好起点。
- 使用
-
标准:
- 尽管标准有时会破碎,但它们仍然提供了有用的信息。
-
内核源代码:
- 内核源代码是获取详细信息的最佳来源,可能比想象中不那么令人畏惧。
到这里还不关注吗?
- 内核源代码是获取详细信息的最佳来源,可能比想象中不那么令人畏惧。