🐧 Linux 檔案系統權限完整指南:ACL、setuid、setgid、sticky bit 全解析
在 Linux 伺服器實務中,檔案系統權限設計絕對不是只有 chmod 755 這麼簡單。
當你開始面對多人專案目錄、共享資料夾、Web 服務帳號、Log 檔保護與安全稽核需求時,
就會接觸到 ACL(Access Control List)、setuid、setgid 與 sticky bit 等進階機制。
本文從基礎權限復習開始,一路實作到 ACL 與特殊權限設計,協助你建立一套「安全、好維護、可稽核」的檔案權限架構。
一、先快速複習:基本權限與數字表示法
在看 ACL 與特殊位元之前,先用最短的篇幅把基礎觀念對齊:
- 三種身分:檔案擁有者(user)、群組(group)、其他人(others)。
- 三種權限:讀(r)、寫(w)、執行(x)。
- 數字表示:r=4、w=2、x=1,相加得到每一組權限數值。
# 範例:-rwxr-x---
# u g o
# user: r+w+x = 4+2+1 = 7
# group: r+ x = 4+0+1 = 5
# other: -+ -+ - = 0
chmod 750 somefile
# 查看詳細權限與擁有者
ls -l somefile
這個模型簡單好懂,但只支援 「一個擁有者 + 一個群組 + 其他人」 三層角色。 當你需要「多個特定使用者」對同一目錄有不同權限時,就會開始感到吃力,這時就是 ACL 登場的時機。
二、什麼是 ACL?為什麼需要它?
ACL(Access Control List) 可以想成是「更細顆粒度的檔案權限表」,它允許你針對每個使用者或群組,分別設定讀寫執行權限,而不再只能依賴單一群組。
典型使用場景:
- 多人專案目錄:開發者 A、B、C 都能寫入,但其餘人只能讀取。
- 維運帳號:某些維運使用者需要讀取特定 Log,但無法直接變更檔案 owner/group。
- 共用資料夾:特定群組有完整存取權,另外再開放少數人只讀。
要使用 ACL,需要檔案系統支援並啟用對應掛載選項(多數現代 ext4、xfs 預設已支援)。
可以先確認是否有掛載 acl 選項:
# 檢查掛載選項
mount | grep -E 'ext4|xfs'
# 也可看 /etc/fstab 中是否有 acl
grep acl /etc/fstab
三、ACL 基本指令:getfacl / setfacl
常見指令有兩個:
getfacl:查看檔案或目錄的 ACL 設定。setfacl:設定或修改 ACL。
以安裝與使用為例:
# Debian / Ubuntu
sudo apt install acl
# CentOS / RHEL / Rocky / AlmaLinux
sudo dnf install acl
# 檢查看看目前 ACL 情況
getfacl /var/log/messages
3-1. 對單一使用者新增 ACL 權限
假設有一個目錄 /data/share,owner 與 group 已設定好,但你想額外給 user alice 寫入權限:
# 對 user alice 新增 rwx 權限
sudo setfacl -m u:alice:rwx /data/share
# 檢查看看
getfacl /data/share
輸出會類似:
# file: data/share
# owner: root
# group: project
user::rwx
user:alice:rwx
group::r-x
mask::rwx
other::r-x
3-2. 對群組新增 ACL 權限
若你有一個群組 auditor 專門用來稽核 Log,希望他們能讀特定 Log 目錄:
sudo setfacl -m g:auditor:rx /var/log/app
getfacl /var/log/app
3-3. Default ACL:讓新建立的檔案自動繼承
若只在目錄本身設 ACL,之後新建立的檔案預設仍會依照 umask 與擁有者決定權限。
如果你希望「未來在此目錄底下新增的檔案,都自動繼承 ACL 模式」,就要使用 default ACL:
# 讓 /data/project 中「未來新檔案」自動給 group project rw 權限
sudo setfacl -m d:g:project:rwx /data/project
# 一次設定 user 與 group 的 default ACL
sudo setfacl -m d:u:alice:rwx,d:g:project:rwx /data/project
# 查看 default ACL
getfacl /data/project
你會看到類似:
default:user::rwx
default:user:alice:rwx
default:group::rwx
default:group:project:rwx
default:mask::rwx
default:other::r-x
3-4. 遞迴套用 ACL
若目錄底下已經有很多檔案,想一次調整所有檔案的 ACL,可以加上 -R:
# 對整個目錄結構套用
sudo setfacl -R -m g:project:rwX /data/project
rwX 中的大寫 X 代表「只對目錄與原本有 x 的檔案加執行權限」,對大批檔案時非常好用。
3-5. 移除 ACL
若要移除特定規則或全部 ACL:
# 移除指定 user 的 ACL
sudo setfacl -x u:alice /data/project
# 移除全部 ACL(包含預設 ACL)
sudo setfacl -b /data/project
四、ACL 常見踩雷與排錯技巧
-
Mask 權限限制:ACL 中的
mask::會限制實際有效權限, 即使你給user:alice:rwx,但 mask 只有r-x,實際生效仍是r-x。 -
工具只顯示基本權限:
ls -l只會顯示「三組傳統權限」,若字尾有加號+代表有 ACL:ls -l /data/project drwxrwxr-x+ 2 root project 4096 Nov 24 10:00 project -
備份與還原:某些備份工具預設不保留 ACL,若需要完整還原權限,請確認有支援 ACL 選項(例如
rsync -A)。
# 使用 rsync 保留 ACL (-A) 與 extended attributes (-X)
rsync -aAX /data/project /backup/project
五、setuid / setgid / sticky bit 概念總覽
在傳統 Unix 世界裡,除了 rwx 以外,還有三個「特殊位元」:
- setuid(Set User ID):執行檔在被執行時,以檔案擁有者的身分執行。
- setgid(Set Group ID):可用於執行檔與目錄,讓程序或新檔案繼承特定群組。
- sticky bit:常用在共享目錄,如
/tmp,避免使用者刪除他人檔案。
在 ls -l 的顯示中,這三個特殊位元會取代原本的 x:
rwsr-xr-x→ user 的 x 被替換成s,代表 setuid。rwxr-sr-x→ group 的 x 被替換成s,代表 setgid。rwxrwxrwt→ others 的 x 被替換成t,代表 sticky bit。
六、setuid:以檔案擁有者身分執行
setuid 最常見的例子是 /usr/bin/passwd:
ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Oct 30 12:34 /usr/bin/passwd
前面的 s 表示:passwd 這個程式在執行時,會以 root 身分運作,
如此一來一般使用者就能修改自己的密碼,而不需要直接給 root 權限。
6-1. 如何設定 / 取消 setuid
可以用數字或符號方式設定:
# 用數字表示:4xxx → setuid
chmod 4755 some_binary # 等價於:rwsr-xr-x
# 用符號表示
chmod u+s some_binary # 設定 setuid
chmod u-s some_binary # 取消 setuid
6-2. setuid 的風險與建議
- 風險:若 setuid 程式有漏洞,攻擊者可藉此取得高權限(甚至 root)。
- 建議:
- 避免自寫程式隨意加上 setuid,尤其是解譯型語言(如 Python、Shell)。
- 定期掃描系統上所有 setuid 檔案,確認是否為預期清單。
# 找出系統上所有 setuid 檔案
sudo find / -perm -4000 -type f -xdev -print
七、setgid:程式群組與目錄專案模式
setgid 在「檔案」與「目錄」上的行為不同:
- 對執行檔:程序在執行時會以檔案群組身分執行。
- 對目錄:在該目錄內建立的新檔案,其
group會繼承目錄的群組,而不是使用者主要群組。
7-1. 專案目錄常見設計範本
假設你有一個專案群組 project,所有專案成員都在這個群組裡:
# 建立專案目錄與群組
sudo groupadd project
sudo mkdir -p /srv/project
sudo chown root:project /srv/project
# 設定目錄群組為 project,並啟用 setgid
sudo chmod 2775 /srv/project
2 代表 setgid,775 則是 rwxrwxr-x。
之後所有在 /srv/project 裡新建的檔案,都會自動帶上 project 群組,
避免出現 某些檔案是 user 的主要群組、造成權限不一致 的情況。
# 驗證 setgid 目錄行為
sudo -u alice touch /srv/project/alice.txt
sudo -u bob touch /srv/project/bob.txt
ls -l /srv/project
# 兩個檔案的 group 都應該是 project
7-2. 設定 / 取消目錄 setgid
# 設定目錄 setgid
chmod g+s /srv/project # 在權限顯示會看到 rwsrwsr-x 或 rwxr-sr-x
# 取消目錄 setgid
chmod g-s /srv/project
八、sticky bit:/tmp 為什麼不會被彼此亂刪?
sticky bit 最常碰到的例子是 /tmp:
ls -ld /tmp
drwxrwxrwt 10 root root 4096 Nov 24 10:00 /tmp
最後一個字元是 t,代表 sticky bit。它的作用是:
在此目錄中,只有檔案的擁有者、目錄擁有者或 root 可以刪除檔案,
即使大家對目錄都有寫入權限,也不能隨意刪除他人的檔案。
8-1. 建立共享暫存目錄的範例
如果你想建立一個類似 /tmp 的共享暫存空間:
sudo mkdir /srv/tmp
sudo chmod 1777 /srv/tmp # 1 代表 sticky bit,777 是 rwxrwxrwx
# 或用符號表示
sudo chmod a+rwx,+t /srv/tmp
九、特殊位元數字總整理:4 / 2 / 1 與 7xxx 模式
在使用 chmod 的四位數模式時,最前面一位是「特殊位元」:
- 4xxx:setuid
- 2xxx:setgid
- 1xxx:sticky bit
- 7xxx:setuid + setgid + sticky bit 全開(實務上很少用到)。
# 常見組合範例
chmod 4755 file # setuid + 755
chmod 2755 dir # setgid + 755(常用在專案目錄)
chmod 1777 /tmp # sticky + 777(共享暫存空間)
十、實務範例:如何設計一個「好維護」的權限架構?
10-1. Web 服務檔案與部署流程
假設你有一個 Web App 放在 /var/www/myapp,由 www-data 執行:
# 建立群組與目錄
sudo groupadd webdev
sudo mkdir -p /var/www/myapp
# 專案成員加入 webdev 群組
sudo usermod -aG webdev alice
sudo usermod -aG webdev bob
# 設定目錄擁有者與群組
sudo chown -R www-data:webdev /var/www/myapp
# 設定 setgid,確保新檔案群組一致
sudo chmod 2775 /var/www/myapp
# 若有 CI/CD 帳號,也加入 webdev 群組
sudo usermod -aG webdev gitlab-runner
如此一來:
- Web 程式以
www-data身分運作。 - 專案成員透過
webdev群組共同維護檔案。 - setgid 讓所有新檔案的群組都保持為
webdev,權限清楚且好管理。
10-2. 專案共用目錄 + ACL 精細控制
若你有一個敏感專案目錄,只開放指定人員讀寫:
# 建立群組與目錄
sudo groupadd finance
sudo mkdir -p /srv/finance
sudo chown root:finance /srv/finance
# 目錄基本權限:群組可讀寫,others 無權
sudo chmod 2770 /srv/finance
# 若有兩位外部稽核者只需讀取權限
sudo setfacl -m u:auditor1:rx,u:auditor2:rx /srv/finance
sudo setfacl -m d:u:auditor1:rx,d:u:auditor2:rx /srv/finance
這樣可以:
- 避免為了稽核者建立新群組 / 調整主要群組。
- 清楚分離「專案成員(可寫)」與「稽核者(只能讀)」。
10-3. Log 檔讀取權限控管
很多維運情境只需要讓某些人「看 log」而不需要 root 權限:
# 建立 logreader 群組
sudo groupadd logreader
# 指定 log 目錄群組與權限
sudo chown -R root:logreader /var/log/myapp
sudo chmod -R 2750 /var/log/myapp
# 若應用程式本身需要寫入,可搭配 setgid 或 ACL
sudo setfacl -m u:myapp:rwX /var/log/myapp
十一、安全檢查清單:上線前先自問這幾件事
- 是否有不必要的 setuid 標記?有沒有定期掃描?
- 共享目錄(尤其是 /tmp 類型)是否都有設定 sticky bit?
- 專案目錄是否使用 setgid 確保群組一致,避免「部分檔案權限怪怪的」?
- ACL 是否真的有需要?如果基本 user/group 模型就能滿足,優先使用傳統權限較易維護。
- 備份與還原流程是否有保留 ACL 與 extended attributes?
🧭 行動清單(可以直接照做)
✅ 在測試環境中練習 getfacl / setfacl(單一檔案 + 目錄 + default ACL)
✅ 為你的專案目錄設計一個「群組 + setgid」模式,確保權限一致
✅ 建立一個類似 /tmp 的共享暫存空間,實作 sticky bit
✅ 使用 find 掃描系統上的所有 setuid / setgid 執行檔,整理出「允許清單」
✅ 檢查備份工具設定,確認是否有保留 ACL / xattr(如 rsync -aAX)
🔗 延伸閱讀
- 🛡 Linux SSH 安全加固:金鑰登入、Port 管理與 Fail2Ban 防暴力破解
- 📜 Linux systemd 與 Logrotate 管理:服務啟動與日誌輪替整合實務
- 🧱 Linux 安全防護大補帖:SELinux、AppArmor、Auditd 與 Fail2Ban 整合指南
- 🌐 Linux Nginx 反向代理與 HTTPS:從單一站台到簡易負載平衡
- 📦 Linux 伺服器從安裝到 Hardening:帳號、Firewall、更新策略一次搞定
— WWFandy・Linux 權限與安全筆記
沒有留言: