傳統 Unix「Root 全權、普通用戶零權」的二元權限模型,導致任何需特權操作的程序(如綁定 1024 以下端口、讀取影子文件、載入內核模組)都必須以 Root 運行,極大擴大了攻擊面。Linux 2.2+ 引入 POSIX.1e Capabilities (權能),將 Root 權限拆解為 30+ 獨立權能,實現細粒度最小權限授權。本文系統解析 Capabilities 概念、內核實現、完整權能清單、實戰應用與安全加固策略。
每個進程擁有三組 64 位位圖(定義於 include/linux/sched.h 的 task_struct):
cap_effective —— 當前生效、內核權檢查依據的權能集。E ⊆ Pcap_permitted —— 進程擁有的最大權能上限,可動態向 E 添加/移除。cap_inheritable —— execve() 後子進程可繼承的權能集。權檢邏輯:內核不再檢查 euid == 0,而是檢查 cap_effective[CAP_X] 對應位是否為 1。例如綁定特權端口檢查 CAP_NET_BIND_SERVICE (bit 10)。
| 權能常數 | 值 | 功能描述 | 典型用例 |
|---|---|---|---|
| CAP_CHOWN | 0 | 改變文件所有者/組 | chown 命令 |
| CAP_DAC_OVERRIDE | 1 | 忽略 DAC 讀寫執行權限檢查 | 備份程序讀取任意文件 |
| CAP_DAC_READ_SEARCH | 2 | 忽略讀/搜索權限檢查 | find 掃描全盤 |
| CAP_FOWNER | 3 | 忽略文件所有者權限檢查(需同 UID) | 刪除自己擁有的只讀文件 |
| CAP_FSETID | 4 | 設定 setuid/setgid 位 | 安裝 setuid 程序 |
| CAP_KILL | 5 | 向非同 UID 進程發送信號 | 管理守護進程 |
| CAP_SETGID | 6 | 改變進程 GID | 服務降權 |
| CAP_SETUID | 7 | 改變進程 UID | 服務降權 |
| CAP_SETPCAP | 8 | 向其他進程轉移/刪除權能 | 權能管理守護進程 |
| CAP_LINUX_IMMUTABLE | 9 | 修改 IMMUTABLE/APPEND_ONLY 屬性 | chattr +i/-i |
| CAP_NET_BIND_SERVICE | 10 | 綁定 1-1023 端口 | Nginx/Apache 啟動 |
| CAP_NET_BROADCAST | 11 | 網絡廣播/多播 | 路由協議守護進程 |
| CAP_NET_ADMIN | 12 | 網絡管理:介面、防火牆、路由 | ip/iptables/route 命令 |
| CAP_NET_RAW | 13 | 使用 RAW 套接字 | ping、tcpdump、nmap |
| CAP_IPC_LOCK | 14 | 鎖定共享內存段 | 高性能資料庫 |
| CAP_IPC_OWNER | 15 | 忽略 IPC 所有權檢查 | 操作任意消息隊列/信號量 |
| CAP_SYS_MODULE | 16 | 載入/卸載內核模組 | modprobe、dkms |
| CAP_SYS_RAWIO | 17 | 訪問 ioperm/iopl (硬體 I/O 端口) | 硬體診斷工具 |
| CAP_SYS_CHROOT | 18 | 使用 chroot() | 容器運行時、ftp 服務 |
| CAP_SYS_PTRACE | 19 | ptrace 任意進程 | gdb、strace、調試器 |
| CAP_SYS_PACCT | 20 | 配置進程記帳 | accton |
| CAP_SYS_ADMIN | 21 | 系統管理:掛載/卸載、配額、swap、reboot | mount、quotaon、swapon |
| CAP_SYS_BOOT | 22 | reboot() 系統調用 | 關機腳本 |
| CAP_SYS_NICE | 23 | 修改進程 nice 值/調度策略 | 實時調度 |
| CAP_SYS_RESOURCE | 24 | 超越資源限制 (RLIMIT) | 高性能服務調優 |
| CAP_SYS_TIME | 25 | 設置系統時鐘/實時時鐘 | ntpd、hwclock |
| CAP_SYS_TTY_CONFIG | 26 | 配置 TTY 設備 | setserial |
| CAP_MKNOD | 27 | 創建特殊文件 (mknod) | 設備節點管理 |
| CAP_LEASE | 28 | 設置文件租約 (fcntl F_SETLEASE) | Samba、NFS 緩存一致性 |
現代內核 (5.x+) 已擴展至 40+ 權能,如 CAP_BPF、CAP_PERFMON、CAP_CHECKPOINT_RESTORE 等。
# 方法一:setcap 賦予二進位文件
setcap 'cap_net_bind_service=+ep' /usr/local/nginx/sbin/nginx
# 驗證
getcap /usr/local/nginx/sbin/nginx
# 輸出:/usr/local/nginx/sbin/nginx = cap_net_bind_service+ep
# 方法二:systemd 服務單元 (推薦,更安全)
# /etc/systemd/system/nginx.service
[Service]
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
User=nginx
Group=nginx
setcap 'cap_net_raw=+ep' /usr/bin/ping
# 移除 setuid 位
chmod u-s /usr/bin/ping
# Docker 運行時移除
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE --cap-add=CHOWN myimage
# Kubernetes Pod 安全上下文
securityContext:
capabilities:
drop: ["ALL"]
add: ["NET_BIND_SERVICE", "CHOWN"]
prctl(PR_CAPBSET_DROP, CAP_X) 可不可逆移除(需重啟恢復)。execve 後權能丟失問題,配合 systemd 實現無 setuid、無文件屬性的權能傳遞。SECURE_NOROOT 禁止 Root 進程自動獲得全權能。# 掃描所有帶有文件權能的可執行文件
getcap -r / 2>/dev/null
# 檢查進程當前權能
cat /proc/$(pidof nginx)/status | grep -i cap
# CapPrm: 0000000000000400 (CAP_NET_BIND_SERVICE)
# CapEff: 0000000000000400
# 審計腳本:發現異常權能賦予
#!/bin/bash
for f in $(getcap -r / 2>/dev/null | cut -d: -f1); do
caps=$(getcap $f | cut -d= -f2)
if [[ $caps =~ (SYS_ADMIN|SYS_MODULE|DAC_OVERRIDE|SYS_RAWIO) ]]; then
echo "HIGH RISK: $f -> $caps"
fi
done
Capabilities 是 Linux 從「全有或全無」向「最小權限」演進的關鍵一步。運維與開發人員應:
drop: [ALL] 並按需 add。掌握 Capabilities,讓每個服務只擁有「剛好夠用」的權力,是構建纵深防御、降低 Root 提權風險的核心技能。