可信macOS应用可执行文件遭静默替换

Lobsters Hottest 新闻

摘要

macOS存在一个漏洞,攻击者可在无需高权限的情况下静默替换受信任应用的可执行文件,从而在权限提示中实施伪装;苹果公司拒绝修复该漏洞。

<p><a href="https://lobste.rs/s/dxaogf/silent_replacement_trusted_macos_app">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/07/24 04:58

# macOS 可信 App 可执行文件的静默替换 来源:https://mysk.blog/2026/07/23/macos-overwrite-app-executables/ macOS 中存在一个漏洞,允许攻击者在无需提升权限的情况下,静默替换任何从网络下载的应用的主可执行文件。因此,当受信任的应用重新启动时,可能会执行攻击者控制的代码,而不会触发安全警告。苹果评估后认为该行为无需修复。 ## 受影响平台 - macOS Tahoe 26.0.0 – 26.5.2 - macOS Golden Gate 27 beta 1、2、3、4 - 更早版本的 macOS 也可能受影响,但未经过测试。 ## 摘要 macOS 提供了多项保护措施,防止应用和脚本篡改其他已安装的应用。在本文中,我们展示了 macOS 的一个 bug,允许攻击者: - 静默替换 `/Contents/MacOS/` 下的应用主可执行文件,无需触发授权提示。 - 正常重新启动修改后的应用,不显示任何安全警告。 - 在系统权限提示中冒充受信任的应用,请求访问钥匙串机密以及受透明度、同意与控制(TCC)保护的文件,包括 `~/Desktop` 和 `~/Documents` 中的内容。 该攻击仅需在当前用户权限下执行代码,无需提升权限。 > ### 面向非技术读者的摘要 > > 我们发现了一个 macOS 安全问题,苹果已查看但决定不予修复。如果你在 Mac 上运行了恶意应用或脚本,攻击者可能: > - 秘密地将你已从网络安装的受信任应用替换为恶意版本。 > - 以这些受信任应用的名义请求访问私有数据的权限,包括你认为私密的文件夹(如桌面或文稿)或钥匙串中的文件。 > > 替换受信任应用无需你的 Mac 密码或任何特殊批准,且可完全在后台进行。访问受保护数据仍需你的批准,但 macOS 系统提示会显示受信任应用的名称和图标,使请求看起来来自真实应用。 ## 背景 ### macOS 应用包 在 macOS 上,应用以 **应用包** 形式分发,这是一种目录结构,在访达中显示为单个 `.app` 文件。应用包包含应用的可执行文件、图标和插图等资源、嵌入的框架和库以及元数据。苹果的文档中描述了更详细的包格式。 当用户从互联网下载应用并首次启动时,macOS 会验证其代码签名和公证,并应用 Gatekeeper 策略来确定该应用是否可信任运行。 在应用安装后(例如拖入 `/Applications`)并打开后,macOS 还会保护其包内的内容。其他应用和脚本,即使以管理员权限运行,也无法修改其中的文件。macOS 会阻止任何此类尝试,并提醒用户已阻止修改。 ## 存档与恢复 我们意外发现了一种场景:任何以当前用户权限运行的应用或脚本都可以静默替换应用包的主可执行文件,并启动修改后的应用而不触发代码签名或安全警告。该问题在以下条件下可复现: 1. 该应用是从网络下载的,而非通过 Mac App Store 安装。App Store 应用归 root 所有,而从网络下载的应用通常归当前用户所有。 2. 该应用已至少启动过一次,从而使 Gatekeeper 完成初步验证。 3. 攻击者已获得当前用户的代码执行权限,例如通过恶意应用或下载的脚本。 我们以 **Signal** 为例。需要明确的是,这 **不是** Signal 的漏洞。Signal 只是一个方便的演示目标,因为它被广泛信任且通过 Mac App Store 外部分发。同样的问题也影响其他从网络下载的应用,包括 Brave Browser、Cursor、Mullvad Browser、Proton Mail、Slack、Visual Studio Code、Xcode 等。 安装 Signal 并首次启动后,macOS 会阻止后续对其应用包的修改。你可以通过运行以下命令验证: ``` % touch /Applications/Signal.app/Contents/MacOS/Signal touch: /Applications/Signal.app/Contents/MacOS/Signal: Operation not permitted ``` 即使使用 `sudo`,你仍然无法修改应用的主可执行文件: ``` % sudo touch /Applications/Signal.app/Contents/MacOS/Signal touch: /Applications/Signal.app/Contents/MacOS/Signal: Operation not permitted ``` 然而,使用 `tar` 存档应用包,删除原始包,再将存档提取回 `/Applications` 会改变此行为: ``` % cd /Applications/ % tar cf .Signal.tar Signal.app % rm -rf Signal.app % tar xf .Signal.tar -C /Applications ``` 恢复后的应用可以正常启动,尽管它是原始包的一个不同副本。令人惊讶的是,其内容可以修改而不触发授权提示: ``` % touch /Applications/Signal.app/Contents/MacOS/Signal % ``` 成功了!视频:存档和恢复应用包后,无需用户授权即可修改其内容。 此时,替换应用的主可执行文件就很简单了。修改后的应用继续启动,macOS 既不显示 Gatekeeper 警告,也不显示其包已被更改的任何迹象。 以下是一个最小示例,使用 Swift 编译一个虚拟可执行文件,然后替换 Signal 的主可执行文件: ``` # 编写一个显示窗口的最小 Swift 程序 cat << EOF > /tmp/dummy.swift import Cocoa let app = NSApplication.shared let window = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 400, height: 200), styleMask: [.titled, .closable, .miniaturizable, .resizable], backing: .buffered, defer: false ) window.center() window.title = "Hi! I'm Signal!" window.makeKeyAndOrderFront(nil) app.activate(ignoringOtherApps: true) app.run() EOF # 编译为命令行 macOS 可执行文件 swiftc -framework Cocoa /tmp/dummy.swift -o /tmp/dummy # 用虚拟二进制替换 Signal 主可执行文件 cp /tmp/dummy /Applications/Signal.app/Contents/MacOS/Signal # 启动修改后的应用(应显示窗口,而非真实 Signal) open /Applications/Signal.app ``` 这种行为与 macOS 代码签名保护应用包的方式一致。包的资源通过存储在 `_CodeSignature/CodeResources` 文件中的哈希进行密封,而主可执行文件带有自己的嵌入代码签名。由于存档和恢复过程使包资源保持不变,它们的哈希继续验证成功。然而,替换后的可执行文件是 ad hoc 签名的,macOS 允许 ad hoc 签名的可执行文件运行。因此,尽管原始可执行文件已被替换,修改后的应用包仍能成功启动。 看起来不一致的是,macOS 仍将修改后的包识别为同一个受信任的应用——尽管并非完全如此,因为替换后的可执行文件仍然会触发钥匙串和 TCC 提示,如下一节所述。一旦原始开发者签名的可执行文件被替换为 ad hoc 签名的可执行文件,我们期望 macOS 将此包视为不同的应用,并要求重新建立信任。 这解释了为什么应用必须先成功启动。如果在首次启动前替换其主可执行文件,初始验证会失败,macOS 会报告该应用已损坏,应移至废纸篓。如果在首次启动后替换可执行文件,则修改后的包会以原应用的身份继续启动。 ## 概念验证攻击 有了这些基础,我们可以创建一个简单的概念验证:存档应用包,恢复它,替换其主可执行文件,然后启动修改后的应用。替换后的可执行文件是 ad hoc 签名的,因此不会继承原始应用的代码签名身份或先前授予的权限。尝试访问钥匙串项目或受 TCC 保护的文件仍然会触发 macOS 授权提示。 在此演示中,替换后的可执行文件尝试执行以下操作: 1. 访问 Signal 存储其加密密钥的钥匙串项目。 2. 访问受 TCC 保护的 `~/Desktop` 和 `~/Documents` 文件夹。 3. 在收集目标机密后,终止自身并重新启动原始 Signal 可执行文件,以使攻击不那么明显。 尽管 macOS 正确要求用户批准访问,但这些提示具有误导性。由于替换后的可执行文件位于 `Signal.app` 内部,它们会显示 Signal 的名称和图标,看起来像是来自真实应用。 当修改后的 Signal 可执行文件请求访问钥匙串项目时,macOS 显示授权提示。该提示使用 Signal 的名称和图标,使其看起来像是来自真实应用。 信任 Signal 的用户可能会批准这些请求,认为它们来自原始应用。一旦批准,替换后的可执行文件就能访问所请求的资源,尽管它是 ad hoc 签名的,且与 Signal 的开发者无关。 当修改后的 Signal 可执行文件请求访问桌面文件夹时,macOS 会显示此提示:该提示在视觉上与合法应用生成的提示无法区分。 作为对比,来自终端的请求会产生相同的 macOS 授权提示。 此概念验证并未绕过 TCC、钥匙串保护或代码签名。它而是利用用户对已安装应用的信任:由于这些提示是真实的 macOS 系统提示,它们在视觉上与真实应用生成的提示无法区分。 以下是概念验证的实际运行情况。为了便于理解每一步,替换后的可执行文件显示一个带有按钮的窗口,触发各个操作。真正的攻击可以在后台自动执行这些操作,无需显示界面。 ## 苹果的评估 苹果得出结论,报告的行为不构成安全问题,原因如下: - 概念验证替换了整个应用包,而不是修改现有的已签名可执行文件。 - 攻击需要当前用户的代码执行权限,且仅影响该用户拥有的应用。 - 替换后的可执行文件不会继承原始应用的授权或先前授予的 TCC 权限,需要用户批准新的授权提示。 - 苹果认为说服用户批准这些提示属于社会工程学问题,而非绕过 TCC 或其他安全机制。 - Gatekeeper 旨在评估下载应用在首次启动前的行为,并非用于保护已由当前用户拥有和修改的文件。 基于这些发现,苹果认定既未绕过 Gatekeeper 也未绕过 TCC,该报告无需安全修复。 ## 讨论 此行为并未绕过 Gatekeeper 或 TCC。然而,它允许攻击者静默替换受信任应用的主可执行文件,并通过真实但具有误导性的系统提示利用这种信任。 在授权提示中重新验证修改后的应用包或识别请求可执行文件的代码签名身份,将显著降低攻击的有效性。 - 在应用包发生变化且启动前重新验证其代码签名。修改后 macOS 显示的短暂验证过程表明它已经检测到了更改。 - 改进授权提示,显示请求访问的可执行文件的代码签名身份(开发者或团队 ID),而不仅仅是应用的名称和图标。 ## 演示与视频 ### 视频:替换 Signal 的主可执行文件 ## 报告时间线 | 日期 | 事件 | |------|------| | **2026 年 6 月 4 日** | Mysk 向苹果提交报告。 | | 2026 年 6 月 9 日 | 苹果请求更多信息。 | | 2026 年 6 月 11 日 | Mysk 发送概念验证源代码。 | | 2026 年 7 月 13 日 | Mysk 请求更新,并讨论是否向 Proton、Signal、Brave 和 Mullvad 披露。 | | 2026 年 7 月 14 日 | 苹果回复:“我们已初步尝试复现此报告。” | | **2026 年 7 月 14 日** | 苹果关闭该报告。 |

相似文章

CVE-2026-28952:Apple macOS 26.5 内核漏洞由 Claude 发现

Hacker News Top

Apple 发布了 macOS Tahoe 26.5 的安全更新,修复了多个漏洞,包括内核错误、拒绝服务攻击和沙盒逃逸。该更新修复了由不同研究人员发现的多个 CVE 漏洞,其中 CVE-2026-28952 据称由 Claude AI 发现。