刚刚阅读了 Stefan Esser 在 https://www.sektioneins.de/en/blog/15-07-07-dyld_print_to_file_lpe.html上报告的 DYLD 权限提升漏洞
我知道这允许任何人在文件系统中的任何位置创建或打开 root 拥有的任意文件,但我想更多地了解将文件描述符泄漏到子进程如何使这比没有时造成更大的威胁。
刚刚阅读了 Stefan Esser 在 https://www.sektioneins.de/en/blog/15-07-07-dyld_print_to_file_lpe.html上报告的 DYLD 权限提升漏洞
我知道这允许任何人在文件系统中的任何位置创建或打开 root 拥有的任意文件,但我想更多地了解将文件描述符泄漏到子进程如何使这比没有时造成更大的威胁。
设置时:
DYLD_PRINT_TO_FILE=/tmp/log some_command
MacOS X 动态加载器将/tmp/log
作为日志文件打开,即附加访问动态加载器中潜在的调试问题。该文件以 shell 调用上下文中的第一个空闲文件描述符打开,即 3。因此文件描述符关联为:
0 → stdin
1 → stdout
2 → stderr
3 → /tmp/log
在这种情况下,该过程some_command
是分叉的。
不幸的是,动态加载器没有关闭 3. 因此,该进程some_command
正在运行一个打开的文件,它从来不需要打开,也从来没有经过正常的文件系统访问控制。这可能是一个文件,some_command
如果它通常试图打开它,则应该无法访问它。
例如,虽然它newgrp
是一个 setuid 二进制文件,但它不能写入正确保护的文件:
$newgrp $ echo '#comment' >&3 zsh: 3: 错误的文件描述符
这个错误是正常的,分叉的 shellnewgrp
没有打开文件描述符 3,因为lsof
可以清楚地看到它(查看 FD 列的 3):
$ lsof -p $$ 命令 PID 用户 FD 类型 设备尺寸/关闭节点名称 [...] zsh 2405 bob 0u CHR 16,3 0t28 1405 /dev/ttys003 zsh 2405 bob 1u CHR 16,3 0t28 1405 /dev/ttys003 zsh 2405 bob 2u CHR 16,3 0t28 1405 /dev/ttys003 zsh 2405 bob 5(已撤销) [...]
但是由于动态加载器中没有关闭3:
$ DYLD_PRINT_TO_FILE=/etc/sudoers newgrp $ echo '#comment' >&3 $
当心:这里没有错误消息意味着echo
有效。并且还lsof
显示了这个漏洞(第 3w 行,这意味着文件描述符 3 以写访问权限打开):
$ lsof -p $$ 命令 PID 用户 FD 类型 设备尺寸/关闭节点名称 [...] zsh 2430 bob 0u CHR 16,3 0t1024 1405 /dev/ttys003 zsh 2430 bob 1u CHR 16,3 0t1024 1405 /dev/ttys003 zsh 2430 bob 2u CHR 16,3 0t1024 1405 /dev/ttys003 zsh 2430 bob 3w REG 1,7 1293 2034681610 /private/etc/sudoers zsh 2430 bob 5(已撤销) [...]
如果它不应该发生,将允许newgrp
写入文件。/etc/sudoers
/etc/sudoers
如果您尝试此示例,即使此示例是无害的,也不要忘记清理您的事后。它的最后一行包含 now #comment
。
newgrp
是一个 UNIX 实用程序,它使用新的组 ID 执行 shell(请参阅UNIX 规范页面)。此实用程序需要 root 权限,因为它可以将组 ID 更改为当前 shell 组列表之外的一个(例如,更改为 uid 组列表中的任何组)。因此,newgrp 是一个启动 shell 的 setuid 根应用程序。
DYLD_PRINT_TO_FILE
是一个dyld
(OS X 动态链接器)环境变量,它告诉 dyld 在哪里打印调试信息。在 OS X 10.10 "Yosemite" 中添加了这个特定变量。它只是众多DYLD_
变量之一,便于调试共享库加载。当dyld
sees
时DYLD_PRINT_TO_FILE
,它会打开一个连接到指定文件的新文件描述符。由于 fds 0、1、2 已经连接到 stdin、stdout 和 stderr,因此文件以 fd 3 打开。值得注意的是,由于newgrp
以 root 身份启动,因此使用 root 的权限打开文件,即使newgrp
后来放弃了生成 shell 的权限。
因为DYLD_
环境变量可以以意想不到的方式修改程序的行为(特别是DYLD_INSERT_LIBRARIES
,OS X 等效的LD_PRELOAD
),所以它们通常在运行 setuid 程序之前被删除或清理。DYLD_PRINT_TO_FILE
苹果在运送优胜美地时显然忘记对新产品进行消毒,从而暴露了这个特殊的缺陷。
最后,(外部)echo 命令告诉生成的子shellnewgrp
执行(内部)echo 命令,该命令将字符串输出$(whoami) ALL=(ALL) NOPASSWD:ALL
到 fd 3,即 now /etc/sudoers
。这一行告诉 sudo,任何帐户都可以通过 sudo 访问,并且使用 sudo 不需要密码。
然后子shell 退出(不再运行命令),最后一个命令sudo -s
执行。由于 sudo 不再需要密码,并且所有帐户都可以使用 sudo,因此sudo -s
只需立即打开一个 root shell,无需提示。
OS Xdyld
实际上确实DYLD_
从应用程序环境中删除了所有变量setuid
,正如您pruneEnvironmentVariables
在dyld.cpp
. 那么为什么这个错误存在呢?答案是DYLD_PRINT_TO_FILE
在清理之前处理得很好 - 事实上,它基本上是dyld
启动后要做的第一件事(参见_main
参考资料dyld.cpp
)。因此,Apple 的修复应该非常简单:只有在环境经过适当清理后才能打开文件。