CVE-2024-27822:macOS PackageKit 权限提升
PackageKit.framework又一个有趣的漏洞!这次是在运行基于 ZSH 的 PKG 时通过 Apple 进行本地特权升级🎉。
已解决的版本:
macOS 14.5 Beta 2 (23F5059e) 及更高版本
macOS 13.6.7 (22G720) 及更高版本
macOS 12.7.5 (21H1222) 及更高版本
受影响的版本:
macOS 14.5 Beta 1 (23F5049f) 及更早版本
macOS 13.6.6 (22G630) 及更早版本
macOS 12.7.4 (21H1123) 及更早版本
任何版本的 macOS 11 或更早版本
概念证明:
源代码:pkg_exploit.py
CVE 相关:CVE-2024-27822
薪酬:无
所用术语:
PKG:macOS 包文件(.pkg,包含安装脚本和要在系统上安装的文件。)
Shebang:#!在脚本开始时指定要使用的解释器的路径。
ZSH:macOS 中的默认 shell 解释器(其他包括 sh 和 bash)
MDM:移动设备管理。
Munki:一个开源的 macOS 软件部署工具。
漏洞详细信息
简单来说:Apple 的Installer.app /会在当前用户环境中以root 身份PackageKit.framework生成嵌入在 PKG 中的安装脚本。这会导致shebang启动其自己的特殊逻辑,例如在以root权限运行时加载用户的文件。#!/bin/zsh
.zshenv
这允许将恶意负载插入到.zshenv文件中,然后当用户安装基于 ZSH 的 PKG 时,该负载将以 root 身份执行。
注意:虽然大多数 PKG 都以 root 身份运行,但有些 PKG 可能以当前用户身份运行,例如WebEx。
此漏洞主要针对用户启动的 PKG 安装。MDM (移动设备管理)和基于Munki的安装不受此漏洞影响,因为它们是在 root 用户的上下文中生成的。
该漏洞的主要攻击场景是,基于逻辑炸弹的有效载荷可以随时等待用户安装基于 ZSH 的 PKG,然后执行有效载荷并获得 root 访问权限。https://www.beyondtrust.com/resources/glossary/logic-bomb
有趣的事实:此漏洞似乎是CVE-2021-30892的扩展:Shrootless以类似的方式滥用环境文件。https://www.microsoft.com/en-us/security/blog/2021/10/28/microsoft-finds-new-macos-vulnerability-shrootless-that-could-bypass-system-integrity-protection/
概念验证
为了演示此漏洞,您只需要一个带有安装脚本的 PKG,该脚本包含 shebang #!/bin/zsh。在脚本执行时(即 PKG 安装),脚本将加载用户的.zshenv文件,该文件中可能嵌入了恶意代码。
重现步骤:
1、向文件中注入恶意负载.zshenv:
/usr/bin/osascript -e "display dialog \"Hello from malware!
Current user: $(/usr/bin/whoami)UID: $UIDEUID: $EUID\""
2、使用 shebang 安装 PKG #!/bin/zsh。例如Generic-ZSH.pkg(https://khronokernel.com/Binaries/Apple%20PackageKit/Generic-ZSH.pkg)
3、观看魔术发生!
pkg_exploit.py(https://khronokernel.com/Binaries/Apple%20PackageKit/pkg_exploit.py)中提供了一个自动化 PoC ,它将创建一个虚拟 PKG 并将有效载荷注入.zshenv文件中。
漏洞发现
2024 年 3 月 14 日,我注意到MacAdmins Slack上出现了一个新的 CVE :CVE-2024-27301
如前所述,此漏洞基于 #!/bin/zsh 脚本中的 shebang。
当了解到这一点时,我认为这是使用 shell 作为 shebang 的一个固有问题,因此开发人员需要更加谨慎地调用它们(即确保永远不会加载不受信任的设置)。
内部审计
在检查了我们内部 PKG 中使用的脚本后,我们将参数附加--no-rcs到了 ZSH shebang 中。这可以防止脚本加载当前用户的环境文件,从而防止漏洞的发生。
然后,我们检查了每个供应商的 PKG。其中一个供应商Watchman Monitoring 的安装程序容易受到此漏洞的攻击。我们向供应商报告了此事,Allen Hancock /Watchman Monitoring 建议我们在他们处理此问题时向 Apple 报告此事。我们于同一天(3 月 14 日)向 Apple 报告,Apple 将其分配给了OE1972568773511。
Watchman Monitoring 于 4 月 5 日发布了修订后的安装程序,版本为7.1.3.101。
惊喜的 macOS 14.5 版本发布
5 月 15 日,我收到一条消息,祝贺我获得 CVE?我很困惑,但查看了macOS 14.5 安全说明,我发现了:
PackageKit Available for: macOS Sonoma Impact: An app may be able to gain root privileges Description: A logic issue was addressed with improved restrictions. CVE-2024-27822: Scott Johnson, Mykola Grymalyuk of RIPEDA Consulting, Jordy Witteman, and Carlos Polop
虽然我不知道其他研究人员也报告过这个漏洞,但我觉得被授予荣誉有点奇怪,因为实际上我只是注意到了另一个 CVE,并且有一个供应商要求向 Apple 提交报告。此外,自 3 月份首次报告以来,我还没有收到 Apple 关于该报告状态的回复。
然而,我会接受我能得到的东西,并由衷感谢苹果公司给予我信用,而不是提交“重复”并继续其他操作。
时间线
逆向工程 PackageKit:苹果的修复方法
现在到了有趣的部分:Apple 是如何修复此漏洞的?
首先,让我们PackageKit在 Hopper 中加载:
/System/Library/PrivateFrameworks/PackageKit.framework/Versions/A/PackageKit
我们首先注意到的是,Apple 添加了一个新的环境变量PackageKit:APPLE_PKGKIT_ESCALATING_ROOT。这用于确定软件包是否以 root 身份运行,目前仅在两个函数中引用:
-[PKInstallDaemon startListeningForConnectionsToService:]
-[PKRunPackageScriptInstallOperation_scriptTaskEnvironmentForPackage:destination:scriptName:]
1. 启动 ListeningForConnectionsToService
第一个函数是 XPC 服务的主要监听器,检查服务是否可用com.apple.installd.user。如果不是,它将尝试将APPLE_PKGKIT_ESCALATING_ROOT环境变量设置为 1:
-(void)startListeningForConnectionsToService:(NSString *)process {
/// ...
if ([process isEqualToString:@"com.apple.installd.user"] == 0x0) {
setenv("APPLE_PKGKIT_ESCALATING_ROOT", "1", 1);
}
/// ...
}
2. _scriptTaskEnvironmentForPackage
第二个函数只是将环境变量传递给脚本的环境,以供最终使用:
-(int)_scriptTaskEnvironmentForPackage:(int)arg2 destination:(int)arg3 scriptName:(int)arg4 {
/// ...
char *rootEnv = getenv("APPLE_PKGKIT_ESCALATING_ROOT");
if (rootEnv != NULL) {
NSString *rootEnvStr = [NSString stringWithUTF8String:rootEnv];
[environment setObject:rootEnvStr forKey:@"APPLE_PKGKIT_ESCALATING_ROOT"];
}
/// ...
}
等等,这没什么作用……
正确!实际修复位于 内部/bin/zsh。
3. /bin/zsh
如果我们在 Hopper 中加载此二进制文件,我们会注意到_run_init_scripts()现在检查环境变量APPLE_PKGKIT_ESCALATING_ROOT。如果已设置,它将跳过加载用户的.zshenv文件:
int _run_init_scripts(int arg0, int arg1) {
/// ...
if (getenv("APPLE_PKGKIT_ESCALATING_ROOT") == 0x0) {
_sourcehome(".zshenv");
}
/// ...
}
是的,修复就是这么简单!
4. /bin/bash(奖励!)
/bin/bash也没有遗漏!在二进制文件的 EntryPoint 中添加了类似的检查:
开发人员建议
开发人员需要记住的是,他们仍应确保脚本中的工作环境干净且不会加载不受信任的设置。这对于以 root 身份运行的脚本(如 PKG 中的脚本)尤其重要,因为我们不能总是依赖操作系统来保护我们。
防止加载不受信任的设置的方法:
SH:(在 macOS 中#!/bin/sh,sh如果没有明确告知,则不会加载任何外部设置)
ZSH:#!/bin/zsh --no-rcs
bash:#!/bin/bash --noprofile --norc
此外,请尽可能始终在脚本中指定二进制文件的完整路径,因为PATH可能并不总是可信的并且可能指向恶意二进制文件。
例如,/bin/mkdir而不是mkdir
用于where <command>查找命令的完整路径
例如where osascript将返回/usr/bin/osascript
糟糕的脚本:
function makeDirectory() {
mkdir $1
}
更好的脚本:
function makeDirectory() {
/bin/mkdir $1
}
结论
这是一个简单的漏洞,但看看 Apple 如何通过 PackageKit/ZSH 和 Bash 缓解它确实很有趣。然而,这确实给不使用标准 shell shebangs 的软件包带来了担忧,例如!#/usr/bin/perl,因为如果编写不当,它们仍可能加载不受信任的设置。
否则,对于那些想要更多基于 PKG 的漏洞的人来说,强烈建议阅读以下内容:
Jonathan Bar Or 的 CVE-2021-30892:Shrootless。
几乎相同的漏洞,但至少他们获得了系统完整性绕过😛。
CVE-2024-27822: macOS PackageKit Privilege Escalation
https://khronokernel.com/macos/2024/06/03/CVE-2024-27822.html