Suzu macOS Playground

M04 · 階梯 2 · L2

Gatekeeper、quarantine 與 XProtect

com.apple.quarantine 四欄位、各下載通道是否附旗標、Gatekeeper 首次執行評估(簽章→公證→stapling)、App Translocation、XProtect,與 Sequoia 起的政策變更。

● 前置:M03 spctl · xattr · stapler · codesign · system_profiler

簽章只回答一半:「能不能信」

M03 的 CDHash 與 entitlements 回答「這支東西是不是它宣稱的樣子」。Gatekeeper 回答另一半:「這支東西怎麼來的、該不該讓它第一次跑」。兩者正交——一支簽得好好的程式,若帶著「下載自網路」的記號且未經 Apple 公證,照樣被擋。

關鍵字只有一個:quarantine。

Gatekeeper 評估實驗室

① 下載通道

瀏覽器啟用 LSFileQuarantineEnabled,下載即附 com.apple.quarantine。

② com.apple.quarantine 解碼
flags
0x0081 · 未評估
時間
2020-04-05T17:58:24.000Z
agent
Safari
UUID
A1B2C3D4-0000-4000-8000-000000000001
旗標位
0x0001 LaunchServices 內部旗標(下載來源/類型相關)。0x0080 LaunchServices 內部旗標(常見於瀏覽器下載)。

UUID 是 LaunchServices QuarantineEventsV2 資料庫的鍵,存原始下載 URL/來源。

③ 情境(首次執行)

quarantine:有(由①通道決定)

判定擋下
  1. quarantine有 com.apple.quarantine 且為首次執行 → 觸發 Gatekeeper 評估。
  2. code signing簽章有效。
  3. notarization未經 Apple 公證(notarize)→「Apple 無法驗證其不含惡意軟體」。

被 Gatekeeper 擋下。

XProtect(簽章式惡意程式掃描,yara)在執行時比對;XProtect Remediator 週期掃描。 模型邊界:本流程為教學決策模型,非真實 syspolicyd 逐位元;quarantine flags 部分位元為 LaunchServices 內部、標為推測。驗證於 macOS 26.3.1(見章末真機卡)。

com.apple.quarantine:一個 xattr,四個欄位

當「會負責的」App 把檔案落地時,它替檔案加一個延伸屬性 com.apple.quarantine,四欄、分號分隔:

0081;5e8a1c40;Safari;A1B2C3D4-0000-4000-8000-0000000000001
└┬─┘ └───┬──┘ └─┬──┘ └──────────────┬──────────────────┘
flags  時戳(hex) 來源 App        事件 UUID
  • flags:LaunchServices 內部位元(部分未公開)。常見解讀:0x0040 代表「已通過 Gatekeeper 評估/使用者已核可」,之後不再提示。
  • 時戳:十六進位的 Unix 秒數。
  • agent:把檔案落地的程式(Safari、sharingd=AirDrop、Mail…)。
  • UUID:~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2 這個資料庫的鍵,存原始下載 URL/來源。

實驗室左欄可貼任意 quarantine 字串解碼。

哪些通道會附旗標?(繞過面的起點)

這是 M04 最重要的直覺:不是所有下載都會被 quarantine。

通道附 quarantine?為什麼
Safari/Arc/Chrome、Mail、Messages、AirDrop(sharingd)✅啟用 LSFileQuarantineEnabled,落地即附旗標
Archive Utility 解壓✅(繼承)壓縮檔本身被 quarantine → 解出的檔案傳播旗標
curl / wget / scp / git clone❌CLI 工具不附 quarantine

沒有 quarantine 旗標 → 首次執行不觸發 Gatekeeper。所以「叫使用者用 curl 抓、或先用會去旗標的工具處理」是真實世界繞過 Gatekeeper 的常見起點。防禦面(M14)反過來把「執行了沒有 quarantine 來源的新二進位」當訊號。

Gatekeeper 首次執行評估

有 quarantine 且是第一次跑時,Gatekeeper(syspolicyd)逐關評估:

  1. 簽章:未簽 →「未識別的開發者」;簽了但無效(被竄改,cdhash 不符)→ 拒絕。
  2. 公證 notarization:Developer ID 程式必須經 Apple 公證掃過惡意特徵。未公證 →「Apple 無法驗證其不含惡意軟體」。
  3. 票根來源:stapler staple 把票根釘進程式 → 離線可驗;否則 Gatekeeper 向 Apple 線上查票根——離線又沒 staple 就驗不了。
  4. 使用者覆寫:被擋時,可在「系統設定 → 隱私與安全性」按「仍要打開」,per-app 放行(簽章損毀者通常仍不行)。

通過後首次仍可能提示「此 App 下載自網路,確定打開?」,確認後就把 0x0040 記上、不再問。實驗室右欄可逐項切換看判定怎麼變。

⚠ Sequoia 起的政策變更(DESIGN.md §11 P1):macOS 15 Sequoia 起,spctl 修改全域評估狀態的操作(舊稱 --master-disable,新版 man page 為 --global-disable)已不再受支援——指令還在、但會要你去系統設定確認,CLI 無法再一鍵把 Gatekeeper 設成「任何來源」;要改全域只能透過 MDM 設定描述檔(systempolicycontrol)。日常仍是逐 App 在「隱私與安全性」按「仍要打開」。本機 macOS 26.3.1 實測 spctl --master-disable 回「needs to be confirmed in System Settings」。

App Translocation:路徑也會騙你

被 quarantine 的 App 若直接從非標準位置(例如 ~/Downloads)執行、且使用者沒把它搬走,macOS 會把它「translocate」到一個唯讀的隨機路徑執行:

/private/var/folders/<xx>/<yy>/T/AppTranslocation/<UUID>/d/Foo.app

目的:瓦解「把惡意 dylib 放在 App 旁、靠相對路徑載入」的詭計——因為 App 看到的自身路徑是隨機唯讀的,旁邊沒有攻擊者放的檔案。把 App 搬進 /Applications(使用者明確移動)即解除 translocation。

XProtect:簽章式掃描

Gatekeeper 管「來源信任」,XProtect 管「像不像已知惡意」:以 yara 規則在執行時比對已知惡意特徵;XProtect Remediator 週期性掃描並清除。它是簽章式(已知威脅),不是行為偵測——新型/客製惡意可能漏網,這就是 M14 端點偵測要補的。

🟢 真機操作卡

xattr -l ~/Downloads/某檔                     # 看所有 xattr(含 com.apple.quarantine 四欄)
xattr -p com.apple.quarantine ~/Downloads/某檔 # 只印 quarantine 值
xattr -d com.apple.quarantine ./foo            # 移除 quarantine(你自己的檔案才做)
spctl --status                                 # Gatekeeper 是否啟用(assessments enabled)
spctl -a -vvv /path/App.app                    # 評估某 App:accepted/rejected + source
stapler validate /path/App.app                 # 票根是否已 staple
system_profiler SPInstallHistoryDataType | head # 安裝史
defaults read /Library/Apple/System/Library/CoreServices/XProtect.bundle/Contents/Info.plist CFBundleShortVersionString

實測對照:spctl -a -vvv /System/Applications/Calculator.app →「accepted / source=Apple System」。spctl --status →「assessments enabled」。本機 XProtect 版本 5347(macOS 26.3.1)。⚠ 只對自己的檔案做 xattr -d;別動系統檔(DESIGN.md §10)。


下一步:M05 SIP / rootless — 為什麼連 root 都寫不進 /System?從 csr bitmask 與 SSV 封印談「執行期 MAC」與「開機期 seal」兩層獨立防線。