系統安全與漏洞利用

POSIX 能力(POSIX capabilities)

/ PAH-ziks /

傳統上一個 Unix 行程不是「root」——被允許做絕對所有事——就是幾乎沒有特殊權力的一般使用者。那是一把全有或全無的鑰匙:一個只需「一項」特權能力(例如綁定 80 連接埠)的程式,得以完整 root 身分執行,而若它被劫持,攻擊者就繼承了 root 的「所有」權力。POSIX 能力把 root 的單塊權力拆成許多細小、可分別授予的特權,使程式能恰好持有它所需的那一項,別無其他。

具體而言,核心定義了數十個具名能力,每個解鎖一類特權操作。CAP_NET_BIND_SERVICE 允許綁定 1024 以下的連接埠;CAP_NET_RAW 允許原始通訊端;CAP_SYS_ADMIN 是一個寬泛、危險、涵蓋眾多管理操作的能力;CAP_DAC_OVERRIDE 繞過檔案權限檢查;CAP_CHOWN 允許更改檔案擁有者。每個行程帶有能力集合(permitted、effective、inheritable,以及一個界定永遠最多能取得多少的 bounding 集合)。核心裡的特權操作檢查的是某個「特定」能力,而非 uid 0。所以一個網頁伺服器可以只被給予 CAP_NET_BIND_SERVICE、捨棄其餘一切,那麼——即使被利用——攻擊者也無法例如載入核心模組或讀取任意檔案,因為那些需要行程並不持有的能力。早早捨棄權限、只保留最低限度,就是最小權限的實踐。

它之所以重要,是用於加固常駐程式,也是容器底下的基礎(容器通常被給予一個受限的能力集合,這是它為何弱於主機上完整 root 的一大原因)。誠實的提醒:能力比它看起來更粗、也更會洩漏。CAP_SYS_ADMIN 寬泛到被稱為「新的 root」,而懂核心的攻擊者能把好幾個能力轉化為完整 root。所以能力縮小、但不總能乾淨地界定爆炸半徑;它最有效的用法是與 seccomp、命名空間結合,並在能力不再需要的那一刻就捨棄它。

# 只授予一個二進位檔一項特權,而非以 root 執行它: $ sudo setcap cap_net_bind_service=+ep ./webserver $ ./webserver # 可綁定 80 埠,但無法載入模組、chown 等 # 在 C 中早早捨棄其餘:cap_set_proc(...) 只保留所需

伺服器恰好取得它所需的那一個能力;日後的攻陷搆不到它從未持有的特權。

能力把 root 拆開,但並不完美:CAP_SYS_ADMIN 寬泛到幾乎等同 root,且好幾個能力能被提權成完整 root——它們縮小爆炸半徑,而非保證一道硬邊界。

又称
Linux capabilitiesprocess capabilitiessplitting rootLinux 能力分割 root 權限