一、Linux 权限体系基础:从用户到权限位
在深入 SUID/SGID/ 粘滞位之前,必须先理解 Linux 的用户模型和基础权限。
1.1 Linux 用户模型
- 三类用户:
- 所有者(User):文件 / 目录的创建者,或通过
chown
修改所有者的用户。 - 所属组(Group):文件 / 目录所属的用户组,可通过
chgrp
修改。 - 其他用户(Others):既不是所有者也不属于所属组的用户。
- 所有者(User):文件 / 目录的创建者,或通过
- 用户组的作用:方便批量管理权限,比如将多个用户加入同一个组,统一分配权限。
1.2 基础权限位
每个文件 / 目录有三组权限,每组包含三个标志位:
- 读(r, read):对文件是读取内容,对目录是列出目录下的文件。
- 写(w, write):对文件是修改内容,对目录是创建 / 删除文件。
- 执行(x, execute):对文件是运行程序,对目录是进入目录(
cd
)。 - 表示方法:
- 符号表示:如
rwxr-xr--
,分别对应所有者(rwx)、所属组(r-x)、其他用户(r--)。 - 八进制表示:每类权限对应一个数字(r=4, w=2, x=1),如
754
对应rwxr-xr--
。
- 符号表示:如
二、SUID(Set User ID):权限的 “临时借用”
2.1 SUID 的定义与原理
- 作用:当用户执行一个设置了 SUID 的可执行文件时,临时以文件所有者的身份运行该程序,而不是以用户自身的身份。
- 生效条件:
- 必须是可执行文件(脚本、二进制程序等),设置在目录或不可执行文件上无效。
- 执行时触发,执行结束后权限收回。
- 权限位表示:
- 所有者的执行位(x)被替换为
s
,如原本是rwxr-xr--
(754),设置 SUID 后变为rwsr-xr--
(4754)。 - 如果原本所有者没有执行权限(x=0),则显示为
rwSr-xr--
(即大写 S,表示无效的 SUID)。
- 所有者的执行位(x)被替换为
2.2 典型案例:passwd
命令的 SUID 机制
- 文件路径:
/usr/bin/passwd
,所有者是 root,权限为-rwsr-xr-x
(八进制 4755)。 - 流程解析:
- 普通用户运行
passwd
时,虽然自己不是 root,但程序以 root 权限执行。 - 程序会检查用户输入的旧密码是否正确(用用户自身权限),然后修改
/etc/shadow
(只有 root 能写)。 - 执行完毕后,权限恢复为普通用户。
- 普通用户运行
- 为什么需要 SUID?:密码存储在
/etc/shadow
,只有 root 能写,普通用户必须通过 SUID 程序间接修改。
2.3 设置与取消 SUID
- 设置:
chmod u+s 文件名
或chmod 4755 文件名
(4 表示 SUID 标志)。 - 取消:
chmod u-s 文件名
或chmod 755 文件名
(去掉 4 的标志)。
2.4 安全风险与注意事项
- 风险 1:恶意程序滥用
如果给普通用户可写的文件设置 SUID(如chmod u+s myscript.sh
),恶意用户可能修改脚本内容,以 root 权限运行恶意代码。 - 风险 2:非可执行文件的 SUID 无效
给文本文件设置 SUID(如chmod u+s test.txt
)不会有任何效果,只会显示rwSrw-r--
(大写 S),但无实际作用。 - 检查系统中的 SUID 文件
find / -type f -perm -4000 2>/dev/null # 查找所有设置了SUID的文件
三、SGID(Set Group ID):权限的 “组继承”
3.1 SGID 的双重作用:文件 vs 目录
SGID 有两种不同的行为,取决于作用对象是文件还是目录。
3.1.1 作用于文件:强制继承所属组
- 效果:当一个设置了 SGID 的文件被创建时(比如通过复制、编辑生成新文件),新文件的所属组会继承原文件的所属组,而不是创建者的默认组。
- 典型场景:团队共享文件
假设团队有一个公共文件project.doc
,所属组为devteam
,设置 SGID 后,任何用户修改或新建相关文件时,新文件自动属于devteam
组,方便组内协作。 - 权限位表示:
- 所属组的执行位(x)被替换为
s
,如rwxr-sr-x
(2755),无执行权限时为rw-r-Sr--
(大写 S)。
- 所属组的执行位(x)被替换为
3.1.2 作用于目录:强制组写入
- 效果:当目录设置 SGID 后,在该目录下创建的新文件 / 目录的所属组会自动继承目录的所属组,而不是创建者的默认组。同时,组内成员可以修改彼此的文件(需有
w
权限),但不能删除(删除需要目录的w
权限和文件的所有者权限)。 - 典型场景:团队共享目录
例如,创建一个目录/project/dev
,所属组为devteam
,设置 SGID 后:- 用户 A(属于
devteam
)在目录下创建文件a.txt
,文件所属组为devteam
而非 A 的个人组。 - 用户 B(属于
devteam
)可以修改a.txt
(如果有w
权限),但不能删除,除非 B 是a.txt
的所有者或 root。
- 用户 A(属于
- 权限位表示:与文件类似,目录的 SGID 标志为
rwxr-sr-x
(八进制 2755)。
3.2 设置与取消 SGID
- 设置:
- 文件 / 目录:
chmod g+s 目标
或chmod 2755 目标
(2 表示 SGID 标志)。
- 文件 / 目录:
- 取消:
chmod g-s 目标
或去掉八进制中的 2 标志。
3.3 案例:/var/tmp
目录的 SGID
- 路径:
/var/tmp
,权限为drwxrwsrwt
(1777,粘滞位 + SGID)。 - 作用:
- SGID 确保用户创建的文件所属组为
tmp
组,方便系统服务处理临时文件。 - 粘滞位(见下文)防止非所有者删除文件。
- SGID 确保用户创建的文件所属组为
四、粘滞位(Sticky Bit):目录的 “防删除保护”
4.1 粘滞位的定义与原理
- 作用:仅对目录有效,设置后,目录内的文件只能被以下用户删除或重命名:
- 文件的所有者(User)
- 目录的所有者(User)
- root 用户
- 典型场景:公共临时目录(如
/tmp
、/var/tmp
),允许所有人写入,但只能删除自己的文件。 - 权限位表示:其他用户的执行位(x)被替换为
t
,如drwxrwxrwt
(1777),无执行权限时为drwxrwxrwT
(大写 T,无效粘滞位)。
4.2 设置与取消粘滞位
- 设置:
chmod o+t 目录名
或chmod 1777 目录名
(1 表示粘滞位标志)。 - 取消:
chmod o-t 目录名
或去掉八进制中的 1 标志。
4.3 案例:/tmp
目录的安全机制
- 权限:
drwxrwxrwt
(1777),任何人都可以写入、执行(进入目录),但:- 用户 A 创建的文件
a.txt
,用户 B 即使有w
权限,也无法删除a.txt
,除非 B 是 root 或a.txt
的所有者。
- 用户 A 创建的文件
- 为什么需要粘滞位?:防止恶意用户删除他人的临时文件,导致程序崩溃(如浏览器缓存、数据库临时文件等)。
五、三大特殊权限的对比与总结
特性 | SUID | SGID(文件) | SGID(目录) | 粘滞位 |
---|---|---|---|---|
作用对象 | 可执行文件 | 文件 / 目录 | 目录 | 目录 |
权限改变 | 执行时临时变所有者 | 新文件继承所属组 | 新文件 / 目录继承所属组 | 防非所有者删除 |
标志位 | 所有者的 x 位变 s | 所属组的 x 位变 s | 所属组的 x 位变 s | 其他用户的 x 位变 t |
八进制标志 | 4 | 2 | 2 | 1 |
典型场景 | passwd 、sudo | 团队共享文件 | 团队共享目录 | /tmp 、/var/tmp |
六、实战操作:设置与验证特殊权限
6.1 测试 SUID:创建一个临时提权程序
- 创建脚本
su_test.sh
,内容:#!/bin/bash echo "当前用户:$(whoami)" echo "尝试读取root文件:" cat /root/root.txt # 普通用户无权限,需SUID提权
- 设置所有者为 root(需管理员权限):
sudo chown root:root su_test.sh
- 设置 SUID:
sudo chmod u+s su_test.sh
- 普通用户执行:
./su_test.sh # 输出当前用户为普通用户,但能读取/root/root.txt(因SUID生效)
6.2 测试 SGID 目录:创建团队共享目录
- 创建目录
team_dir
,所属组为devteam
:sudo mkdir /team_dir sudo chgrp devteam /team_dir sudo chmod 2775 /team_dir # SGID+组读写执行,其他用户读执行
- 普通用户(属于
devteam
)在目录内创建文件:touch /team_dir/test.txt ls -l /team_dir/test.txt # 所属组应为devteam,而非用户个人组
6.3 测试粘滞位:公共目录防删除
- 创建目录
public_dir
,设置粘滞位:mkdir public_dir chmod 1777 public_dir
- 用户 A 创建文件
a.txt
,用户 B 尝试删除:# 用户A操作 touch public_dir/a.txt # 用户B操作(假设B不是A,也不是目录所有者或root) rm public_dir/a.txt # 提示权限不足,无法删除
七、安全最佳实践
7.1 谨慎使用 SUID/SGID
- 原则:只对必要的可执行文件设置 SUID,且确保文件不可被普通用户修改(权限为
rwsr-xr-x
,即所有者可写,其他用户不可写)。 - 检查命令:
# 查找系统中所有SUID文件(危险文件可能在/home、/tmp等非系统目录) find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -l {} \; 2>/dev/null
7.2 目录 SGID 的正确配置
- 团队共享目录需同时设置:
- 所属组为团队组(
chgrp devteam dir
) - 权限为
2775
(SGID + 组内读写执行,其他用户读执行) - 禁止其他用户写入(除非需要公共写入)。
- 所属组为团队组(
7.3 粘滞位的适用场景
- 仅在公共写入目录(如
/tmp
)设置粘滞位,私人目录无需设置。 - 避免在重要目录(如
/var
、/etc
)设置粘滞位,可能导致权限混乱。
7.4 权限审计与监控
- 定期检查系统中的特殊权限文件:
# SUID文件(4000) find / -perm -4000 -exec ls -ld {} \; 2>/dev/null # SGID文件(2000) find / -perm -2000 -exec ls -ld {} \; 2>/dev/null # 粘滞位目录(1000) find / -type d -perm -1000 -exec ls -ld {} \; 2>/dev/null
- 使用审计工具(如
auditd
)监控特殊权限文件的修改和执行。
八、常见问题解答
8.1 为什么 SUID 对目录无效?
SUID 的设计初衷是让程序以所有者权限运行,目录没有 “执行” 的概念(进入目录是x
权限),因此 SUID 对目录无意义。如果设置,会显示为d---s--x
(无效标志,因为目录的所有者必须有x
权限才能进入)。
8.2 SGID 文件和目录的区别为什么这么大?
这是 Linux 设计的历史原因:
- 文件的 SGID 最初用于 BSD 系统,让程序运行时继承所属组权限(类似 SUID,但针对组),后来逐渐被目录的 SGID 功能取代。
- 目录的 SGID 更常用,用于强制组继承,方便团队协作。
8.3 粘滞位的名字由来?
早期 UNIX 系统中,粘滞位(Sticky Bit)的作用是 “粘住” 可执行文件在内存中,避免重复加载(如/bin/sh
),后来功能演变为防删除,名字保留下来。
九、总结:特殊权限是把 “双刃剑”
SUID/SGID/ 粘滞位是 Linux 权限体系的高级特性,合理使用能大幅提升协作效率和安全性,但误用可能导致严重漏洞(如 SUID 文件被篡改导致 root 权限丢失)。建议:
- 入门阶段先掌握基础权限(r/w/x),再理解特殊权限的原理和场景。
- 在测试环境反复实践,观察权限变化的实际效果。
- 生产环境中严格控制特殊权限的设置,定期审计系统中的敏感文件。
通过 “公寓小区” 的比喻记住核心逻辑,再通过实战操作加深理解,就能逐步掌握这三个重要概念。Linux 的魅力在于细节,每一个权限位背后都有其设计初衷,耐心拆解就能化繁为简。
【形象比喻版】SUID/SGID/ 粘滞位 ——Linux 权限的 “魔法钥匙”
🌏 场景设定:把 Linux 系统想象成一个 “公寓小区”
- 文件 / 目录:小区里的 “房间” 或 “公共区域”
- 用户:小区里的 “居民”(普通用户是住户,root 是管理员)
- 权限:进入房间的 “钥匙”(读 r = 看房间,写 w = 改房间,执行 x = 进入房间)
1. SUID(Set User ID)——“临时管理员钥匙”
场景:小区里有一个 “密码修改室”(对应/usr/bin/passwd
文件),普通住户(普通用户)想改自己的密码,但密码数据库(/etc/shadow
)只有管理员(root)能修改。
- 正常情况:住户没钥匙进不了管理员的房间,改不了密码。
- SUID 魔法:管理员在 “密码修改室” 上挂了一把 “临时管理员钥匙”(设置 SUID)。
- 当住户进入 “密码修改室” 时,虽然自己是住户身份,但这把钥匙让他暂时拥有管理员的权限,能操作密码数据库。
- 关键点:只有可执行文件能挂 SUID 钥匙,且执行时 “借用文件所有者的权限”(比如文件属于 root,执行时就临时变 root)。
- 类比:就像去图书馆借书记账,虽然你是学生,但用图书馆的 “登记系统”(SUID 程序)时,系统会以管理员身份记录你的操作。
2. SGID(Set Group ID)——“团队共享钥匙”
场景 1:文件的 SGID—— 团队协作文件
小区里有个 “项目资料室”(文件),属于 “开发组”(某个用户组),组内成员可以修改,但希望新创建的文件也自动属于 “开发组”,而不是创建者的个人组。
- SGID 魔法:给 “项目资料室” 设置 SGID 后,任何人在里面创建新文件时,新文件的所属组会继承 “项目资料室” 的组(开发组),而不是创建者的默认组。
- 场景 2:目录的 SGID—— 团队共享目录
如果 “项目资料室” 是一个目录,设置 SGID 后,组内成员在目录里创建文件时,文件自动属于目录的组,且组内成员都能修改彼此的文件(但不能删除,除非有w
权限)。 - 类比:团队共用一个 “共享文件夹”,每个人放进去的文件默认归团队所有,方便协作。
3. 粘滞位(Sticky Bit)——“私人储物柜标签”
场景:小区有个 “公共储物间”(对应/tmp
目录),所有人都能放东西、取东西,但只能删除自己的东西,不能删别人的。
- 粘滞位魔法:给 “公共储物间” 贴上 “粘滞标签” 后,每个住户只能删除自己创建的文件,即使有写入权限,也删不了别人的文件。
- 类比:就像学校的储物柜,每个人只能开自己的柜子,不能拆别人的柜子,哪怕你有整个储物间的钥匙。
🗝️ 总结:三把 “魔法钥匙” 的区别
钥匙类型 | 作用对象 | 效果 | 典型场景 |
---|---|---|---|
SUID | 可执行文件 | 执行时临时获得文件所有者的权限(如 root 的文件,执行时变 root) | passwd 修改密码 |
SGID | 文件 / 目录 | 文件:新创建的文件继承父文件的组;目录:新创建的文件继承目录的组 | 团队共享目录 / 文件 |
粘滞位 | 目录 | 只有文件所有者能删除目录内的文件,即使有写入权限也不行 | 公共临时目录/tmp |