Linux Auth

在 Windows 中模擬 Linux 環境進行練習

  • 使用 Docker 搭建 Linux 容器環境

    • 安裝 Docker Desktop(支援 Windows 10 以上)
    • 使用指令快速啟動 Ubuntu 容器:docker run -it --rm ubuntu
    • 容器內可自由操作 Linux 指令,離開即清除環境
    • 適合安全地練習權限變更、不怕破壞系統

Linux 權限教學文章大綱

一、前言

一直以來在使用 Linux 時,只有熟悉那些常常用到的指令,例如 cp mv rm ll 這些,知道 ll 最前面有一串奇怪的字串是權限,但是從來沒有了解他到底在做什麼

直到最近專案上線,很多鬼故事發生,在某些環境中,原本可以使用的指令,都突然出現 permission denied

Damn,到底是誰動了我的東西,怎麼以前可以的指令現在不行了。

一切都是權限在搞事,要想辦法弄回來。

所以...還是好好了解一下吧...

為什麼權限管理在 Linux 中很重要?

Linux 是一個多使用者、多工的作業系統,權限管理是其核心安全機制。良好的權限管理能夠:

  • 保護系統安全:防止惡意或意外的檔案修改、刪除
  • 確保資料隱私:控制哪些使用者可以存取敏感資訊
  • 維護系統穩定:避免不當操作導致系統崩潰
  • 符合法規要求:企業環境中的資料保護與稽核需求

常見場景

  1. 多人共享伺服器環境

    • 開發團隊共用開發機器
    • 不同專案需要隔離檔案存取權限
    • 防止誤刪他人檔案
  2. Web 服務器權限控制

    • Web 應用程式檔案的存取權限
    • 資料庫檔案保護
    • 設定檔安全性
  3. 系統管理與維運

    • 系統設定檔保護
    • 服務帳號權限最小化
    • 日誌檔案的讀寫控制

二、基本概念

使用者(User)與群組(Group)

使用者(User):

  • 每個檔案都有一個擁有者(owner)
  • 使用者 ID(UID)是系統內部識別碼
  • root 使用者的 UID 為 0,擁有最高權限
  • 一般使用者 UID 通常從 1000 開始

群組(Group):

  • 使用者可以屬於一個或多個群組
  • 群組 ID(GID)是系統內部識別碼
  • 主要群組:使用者的預設群組
  • 附加群組:使用者額外加入的群組
# 查看目前使用者資訊,包含 uid,gid,groups
whoami
id

# 查看使用者所屬群組
groups
groups username

# 查看系統所有使用者
cat /etc/passwd

# 查看系統所有群組
cat /etc/group

檔案與目錄的屬性

每個檔案和目錄都有三種存取對象:

  • Owner(擁有者):檔案的擁有者
  • Group(群組):檔案所屬群組的成員
  • Others(其他人):系統上所有其他使用者

權限種類

基本權限:

  • read (r):讀取權限
    • 檔案:可以查看檔案內容
    • 目錄:可以列出目錄內容(需搭配 execute 權限)
  • write (w):寫入權限
    • 檔案:可以修改檔案內容
    • 目錄:可以在目錄中建立、刪除、重命名檔案
  • execute (x):執行權限
    • 檔案:可以執行檔案(如程式、腳本)
    • 目錄:可以進入目錄(cd 指令)

三、權限表示法

字母表示法

使用 ls -l 指令可以查看詳細權限資訊:

或是也可以使用縮寫 ll

$ ls -l
-rwxr-xr-- 1 user group 1024 Jun 7 10:30 example.txt
drwxr-xr-x 2 user group 4096 Jun 7 10:31 folder

權限字串解析:

-rwxr-xr--
│└┬┘└┬┘└┬┘
│ │  │  └── Others 權限 (r--):只能讀取
│ │  └───── Group 權限 (r-x):可讀取和執行
│ └──────── Owner 權限 (rwx):可讀、寫、執行
└─────────── 檔案類型 (-:一般檔案, d:目錄 dictionary, l:符號連結 link)

權限符號對照:

  • r = read(讀取)
  • w = write(寫入)
  • x = execute(執行)
  • - = 沒有該權限

數字表示法(八進位)

每個權限對應一個數字:

  • r = 4
  • w = 2
  • x = 1

三個數字分別代表 Owner、Group、Others 的權限:

數字 二進位 權限 說明
0 000 --- 無任何權限
1 001 --x 只有執行權限
2 010 -w- 只有寫入權限
3 011 -wx 寫入 + 執行
4 100 r-- 只有讀取權限
5 101 r-x 讀取 + 執行
6 110 rw- 讀取 + 寫入
7 111 rwx 完全權限

常見權限組合:

  • 755:擁有者完全權限,群組和其他人可讀取和執行
  • 644:擁有者可讀寫,群組和其他人只能讀取
  • 700:只有擁有者有完全權限
  • 600:只有擁有者可讀寫

特殊權限

SetUID (SUID):

  • 符號:s 在 owner 的 execute 位置
  • 數字:在權限前加 4(如 4755)
  • 功能:執行檔案時,暫時獲得檔案擁有者的權限
  • 例子:/usr/bin/passwd 指令

SetGID (SGID):

  • 符號:s 在 group 的 execute 位置
  • 數字:在權限前加 2(如 2755)
  • 功能:
    • 檔案:執行時獲得檔案群組權限
    • 目錄:新建檔案自動繼承目錄的群組
    • 也就是說,無論誰執行它,都會以「檔案擁有者(這裡是 root)」的身份來執行
  • 例子:/usr/bin/passwd

Sticky Bit:

  • 符號:t 在 others 的 execute 位置
  • 數字:在權限前加 1(如 1755)
  • 功能:
    • 所有人都可以寫入該目錄(777)
    • 但只能刪除自己建立的檔案
    • 其他人(即使有寫入權限)不能刪除或改動你建立的檔案
  • 例子:/tmp 目錄
# 查看特殊權限範例
ls -l /usr/bin/passwd  # SUID
ls -ld /tmp           # Sticky bit

四、常用指令教學

ls -l:檢視檔案權限

# 查看目前目錄的詳細權限資訊
ls -l
# 等同 ll,以下的指令以 ls -l 開頭的,都可以改成 ll,例如 ls -la = ll -a
ll

# 查看特定檔案權限
ls -l filename.txt

# 查看目錄本身的權限(而非目錄內容)
ls -ld dirname

# 查看隱藏檔案權限
ls -la

# 以人類可讀格式顯示檔案大小
ls -lh

輸出解析:

-rw-r--r-- 1 user group 1024 Jun 7 10:30 file.txt
│    │     │  │    │     │    │         └── 檔案名稱
│    │     │  │    │     │    └─────────── 修改時間
│    │     │  │    │     └──────────────── 檔案大小
│    │     │  │    └────────────────────── 群組名稱
│    │     │  └─────────────────────────── 使用者名稱
│    │     └────────────────────────────── 硬連結數量
│    └──────────────────────────────────── 檔案權限(前三為 owner、中三為 group、後三維 others)
└───────────────────────────────────────── 檔案類型

硬連結 數量表示有多少個連結指向這個檔案,對於目錄來說,這個數字會包含子目錄的連結數。 假設我用 touch 建立一個 txt 檔案,使用 ll 時看到的硬連結束自為 1 再用 ln 建立一個硬連結的另外一個檔案,再使用 ll,就會看到這兩個檔案的硬連結數字變成 2 修改其中一個檔案,另外一個也會被做一樣的修改。因為實際上這兩個檔案是同一個。

chmod:變更權限

數字模式:

# 設定權限為 755 (rwxr-xr-x)
chmod 755 filename

# 設定權限為 644 (rw-r--r--)
chmod 644 filename

# 遞迴設定目錄及其內容權限
chmod -R 755 directory

# 設定特殊權限
chmod 4755 filename  # SUID + 755
chmod 2755 dirname   # SGID + 755
chmod 1755 dirname   # Sticky + 755

符號模式:

# 語法:chmod [who][operator][permission] filename
# who: u(user), g(group), o(others), a(all)
# operator: +(加入), -(移除), =(設定)
# permission: r(read), w(write), x(execute)

# 給予 owner 執行權限
chmod u+x filename

# 移除 group 寫入權限
chmod g-w filename

# 設定 others 只有讀取權限
chmod o=r filename

# 給所有人加入執行權限
chmod a+x filename
chmod +x filename  # 簡寫

# 組合使用
chmod u+rw,g+r,o-rwx filename

chown:變更檔案擁有者

# 語法:chown [owner][:group] filename

# 變更檔案擁有者
chown newuser filename

# 同時變更擁有者和群組
chown newuser:newgroup filename

# 只變更群組(使用冒號開頭)
chown :newgroup filename

# 遞迴變更目錄及其內容
chown -R newuser:newgroup directory

# 從參考檔案複製權限
chown --reference=ref_file target_file

# 變更符號連結本身的擁有者(而非目標檔案)
chown -h newuser symlink

chgrp:變更檔案群組

# 變更檔案群組
chgrp newgroup filename

# 遞迴變更
chgrp -R newgroup directory

# 從參考檔案複製群組
chgrp --reference=ref_file target_file

# 顯示變更過程
chgrp -v newgroup filename

umask:預設權限設定

umask 決定新建檔案和目錄的預設權限:

# 查看目前 umask 值
umask

# 查看 umask 的符號表示
umask -S

# 設定 umask(數字模式)
umask 022  # 新檔案權限 = 666-022 = 644
           # 新目錄權限 = 777-022 = 755

# 設定 umask(符號模式)
umask u=rwx,g=rx,o=rx

# 臨時設定 umask
umask 077  # 只有擁有者有權限

# 永久設定 umask(寫入 ~/.bashrc)
echo "umask 027" >> ~/.bashrc

umask 計算範例:

  • 檔案預設最大權限:666 (rw-rw-rw-)
  • 目錄預設最大權限:777 (rwxrwxrwx)
  • umask 022:表示移除 group 和 others 的 write 權限
  • 結果:檔案 644 (rw-r--r--),目錄 755 (rwxr-xr-x)

五、進階權限管理

ACL(Access Control List)介紹與設定

傳統的 Linux 權限系統只能為檔案設定一個擁有者、一個群組和其他人的權限。ACL 提供更細緻的權限控制,可以為特定使用者或群組設定個別權限。

ACL 的優勢:

  • 可以為多個不同使用者設定不同權限
  • 不需要建立大量群組
  • 更靈活的權限組合

檢查 ACL 支援:

# 檢查檔案系統是否支援 ACL
mount | grep acl

# 查看檔案是否有 ACL(ls -l 會顯示 + 號)
ls -l filename
-rw-rw-r--+ 1 user group 1024 Jun 7 10:30 filename

ACL 基本指令:

# 安裝 ACL 工具(Ubuntu/Debian)
sudo apt-get install acl

# 查看檔案的 ACL 設定
getfacl filename
getfacl directory

# 設定使用者權限
setfacl -m u:username:rwx filename    # 給予特定使用者 rwx 權限
setfacl -m u:alice:r-- filename       # 給予 alice 只讀權限

# 設定群組權限
setfacl -m g:groupname:rw- filename   # 給予特定群組 rw 權限

# 設定預設 ACL(針對目錄,新檔案會繼承)
setfacl -d -m u:username:rwx directory

# 移除特定 ACL
setfacl -x u:username filename        # 移除特定使用者的 ACL
setfacl -x g:groupname filename       # 移除特定群組的 ACL

# 移除所有 ACL
setfacl -b filename

# 遞迴設定 ACL
setfacl -R -m u:username:rwx directory

# 從檔案讀取 ACL 設定
setfacl --set-file=acl_rules.txt filename

ACL 實用範例:

# 情境:讓 alice 可以讀寫專案目錄,bob 只能讀取
setfacl -m u:alice:rwx project_dir
setfacl -m u:bob:r-x project_dir
setfacl -d -m u:alice:rwx project_dir  # 預設權限
setfacl -d -m u:bob:r-x project_dir

# 備份和還原 ACL
getfacl -R directory > acl_backup.txt
setfacl --restore=acl_backup.txt

六、實作範例

建立使用者與群組並設計權限實例

情境:建立一個專案開發環境,有三種角色:

  • 專案經理(project_manager):完全存取權限
  • 開發人員(developers):可讀寫程式碼,不能修改設定
  • 測試人員(testers):只能讀取和執行,不能修改
# 1. 建立群組
groupadd project_managers
groupadd developers  
groupadd testers

# 2. 建立使用者並加入群組
## -m:就是 --create-home 的縮寫,預設建立 /home/使用者名稱 的路徑,沒有加 -m 的話,有些系統四射不會幫你建立 home 目錄
## -G:就是 --groups 的縮寫,把使用者加入指定的附加群組,一次可以多個 group,用逗號隔開就好
useradd -m -G project_managers alice
useradd -m -G developers bob
useradd -m -G developers charlie
useradd -m -G testers david

# 3. 設定密碼
passwd alice
passwd bob
passwd charlie
passwd david

# 4. 建立專案目錄結構
## -p:即 parant,遞迴建立資料夾
## {xxx,xxxx}:只建立多個子目錄
mkdir -p /project/{src,config,docs,bin}
chown -R alice:project_managers /project

# 5. 設定目錄權限
# 專案根目錄:專案經理完全權限,其他群組可進入
chmod 755 /project

# 原始碼目錄:開發人員可讀寫,測試人員只讀
chgrp developers /project/src
chmod 775 /project/src
setfacl -m g:testers:r-x /project/src

# 設定目錄:只有專案經理可修改
chmod 750 /project/config
setfacl -m g:developers:r-x /project/config
setfacl -m g:testers:r-x /project/config

# 文件目錄:所有人可讀,開發人員和專案經理可寫
chgrp developers /project/docs
chmod 775 /project/docs
setfacl -m g:testers:r-x /project/docs

# 執行檔目錄:所有人可執行,專案經理可修改
chmod 755 /project/bin
setfacl -m g:developers:r-x /project/bin
setfacl -m g:testers:r-x /project/bin

# 6. 設定預設 ACL(新檔案自動繼承權限)
setfacl -d -m g:developers:rw- /project/src
setfacl -d -m g:testers:r-- /project/src

權限錯誤排除範例

常見問題 1:無法進入目錄

# 錯誤:Permission denied when trying to cd into directory
cd: permission denied: /some/directory

# 診斷步驟:
ls -ld /some/directory          # 檢查目錄權限
ls -ld /some                    # 檢查上層目錄權限
getfacl /some/directory         # 檢查 ACL

# 解決方案:確保目錄有 execute 權限
sudo chmod +x /some/directory

常見問題 2:無法建立檔案

# 錯誤:無法在目錄中建立檔案
touch: cannot touch 'newfile': Permission denied

# 診斷步驟:
ls -ld .                        # 檢查目錄權限
id                              # 檢查使用者和群組
df -h .                         # 檢查磁碟空間

# 解決方案:確保目錄有 write 權限
sudo chmod g+w .

常見問題 3:無法執行檔案

# 錯誤:程式無法執行
bash: ./script.sh: Permission denied

# 診斷步驟:
ls -l script.sh                 # 檢查檔案權限
file script.sh                  # 檢查檔案類型

# 解決方案:加入執行權限
chmod +x script.sh

常見問題 4:權限看起來正確但仍無法存取

# 可能原因:SELinux 或 AppArmor 限制
# 診斷:
getenforce                      # 檢查 SELinux 狀態
ausearch -m AVC -ts recent      # 查看 SELinux 拒絕日誌
sudo apparmor_status            # 檢查 AppArmor 狀態

# 暫時解決:
sudo setenforce 0              # 暫時停用 SELinux
sudo aa-complain /path/to/program  # AppArmor 警告模式

使用 find 搭配權限查找異常檔案

# 尋找權限過於寬鬆的檔案
# 1. 找出所有人都可寫入的檔案(潛在安全風險)
find /home -type f -perm -o+w 2>/dev/null

# 2. 找出 SUID 檔案(需要特別注意)
find /usr -type f -perm -4000 2>/dev/null

# 3. 找出 SGID 檔案
find /usr -type f -perm -2000 2>/dev/null

# 4. 找出沒有擁有者的檔案
find /home -nouser 2>/dev/null

# 5. 找出沒有群組的檔案
find /home -nogroup 2>/dev/null

# 尋找特定權限的檔案
# 6. 找出權限為 777 的檔案(完全開放)
find /home -type f -perm 777 2>/dev/null

# 7. 找出權限為 666 的檔案(所有人可讀寫)
find /home -type f -perm 666 2>/dev/null

# 8. 找出擁有者可執行的檔案
find /home -type f -perm -u+x 2>/dev/null

# 尋找最近修改的檔案並檢查權限
# 9. 找出最近 7 天修改且權限異常的檔案
find /var/log -type f -mtime -7 -perm -o+w 2>/dev/null

# 10. 找出大於 100MB 且所有人可讀的檔案
find /home -type f -size +100M -perm -o+r 2>/dev/null

# 批次修復權限問題
# 11. 將所有 .txt 檔案設為 644 權限
find /home/user -name "*.txt" -type f -exec chmod 644 {} \;

# 12. 將所有目錄設為 755 權限
find /home/user -type d -exec chmod 755 {} \;

# 13. 移除所有人的寫入權限(除了擁有者)
find /home/user -type f -exec chmod o-w {} \;

# 生成權限報告
# 14. 生成目錄權限報告
find /project -exec ls -ld {} \; > permissions_report.txt

# 15. 找出可能的安全問題並記錄
{
  echo "=== SUID Files ==="
  find /usr -type f -perm -4000 2>/dev/null
  echo "=== World Writable Files ==="
  find /home -type f -perm -o+w 2>/dev/null
  echo "=== No Owner Files ==="
  find /home -nouser 2>/dev/null
} > security_audit.txt

七、最佳實踐與建議

最小權限原則(Principle of Least Privilege)

核心概念:只給予使用者完成工作所需的最少權限,降低安全風險。

實踐方法:

  1. 使用者權限設計:
# 不好的做法:直接給予 777 權限
chmod 777 /shared/data  # 所有人完全權限

# 好的做法:針對需求設計權限
chmod 750 /shared/data          # 擁有者和群組權限
setfacl -m u:alice:rw- /shared/data    # 給特定使用者讀寫權限
setfacl -m u:bob:r-- /shared/data      # 給特定使用者只讀權限
  1. 服務帳號管理:
# 為服務建立專用使用者(無法登入)
useradd -r -s /bin/false webapp_user
useradd -r -s /bin/false database_user

# 設定服務檔案權限
chown webapp_user:webapp_user /var/www/app
chmod 750 /var/www/app
  1. 目錄權限規劃:
# 分層權限設計
/project/                    # 755 - 專案根目錄
├── src/                     # 770 - 開發人員讀寫
├── config/                  # 750 - 管理員專用
├── public/                  # 755 - 公開讀取
└── logs/                    # 750 - 管理員和服務讀寫

避免使用 root 身份操作

為什麼要避免:

  • root 權限過大,誤操作可能損壞系統
  • 安全審計困難
  • 不符合最小權限原則

替代方案:

  1. 使用 sudo 進行特權操作:
# 設定 sudo 權限(編輯 /etc/sudoers)
sudo visudo

# 給予特定使用者特定指令權限
alice ALL=(ALL) /bin/systemctl restart apache2
bob ALL=(ALL) NOPASSWD: /usr/bin/tail -f /var/log/apache2/*

# 給予群組權限
%developers ALL=(ALL) /usr/bin/docker
  1. 使用 su 切換使用者:
# 切換到特定使用者
su - webapp_user

# 執行特定指令後返回
su -c "systemctl status apache2" root
  1. 使用服務帳號執行應用程式:
# 以特定使用者身份執行服務
sudo -u webapp_user /usr/bin/python3 /var/www/app/app.py

# 設定 systemd 服務使用非 root 使用者
# /etc/systemd/system/myapp.service
[Service]
User=webapp_user
Group=webapp_user
ExecStart=/usr/bin/python3 /var/www/app/app.py
Tags: Linux, Permissions, Security, ACL, Best Practices Uncategorized