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 添加了一个新的环境变量PackageKitAPPLE_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