setuid通过将进程有效uid临时设为文件所有者uid(如root)实现权限提升,仅限可执行文件生效;setgid对文件改进程有效gid,对目录则使新文件继承目录所属组;权限数字中4为setuid、2为setgid,不可随意叠加,且上线前须严格审查必要性、依赖安全与环境变量清理。

setuid 是怎么让普通用户临时变 root 的
它不改变你的登录身份,只在执行那个程序的瞬间,把进程的 effective UID 换成文件所有者的 UID。比如 /usr/bin/passwd 属于 root、带 setuid,你一运行它,内核就悄悄把当前进程的 eUID 设为 0(root),所以它能写 /etc/shadow;但你一退出,权限立刻还原。
- 必须是可执行文件(
chmod +x后才能设setuid),对脚本(如.sh)基本无效——多数 shell 会主动忽略,防止绕过安全限制 - 设置命令是
chmod u+s /path/to/executable,或数字写法chmod 4755 /path/to/executable - 检查是否生效:用
ls -l看所有者 x 位变成s(如-rwsr-xr-x),不是S(大写说明 x 权限没开,setuid 不起作用)
setgid 对目录和文件的作用完全不同
同一个 setgid 标志,在文件和目录上干的是两件事,这点特别容易混淆。
- 对可执行文件:和
setuid类似,只是改的是进程的effective GID,比如/usr/bin/mlocate属于slocate组,设了setgid就能读/var/lib/mlocate/mlocate.db - 对目录:这才是它最常用的地方——新创建的文件/子目录自动继承该目录的所属组,而不是创建者默认的 primary group。命令是
chmod g+s /shared/dir - 验证目录是否生效:新建一个文件,用
ls -l看它的 group 是否和目录一致;如果 group 名显示为?或报错,说明组 ID 已被删除,setgid仍存在但实际失效
为什么 chmod 2755 和 4755 不能混着用
数字权限里,4 是 setuid,2 是 setgid,1 是 sticky bit。它们可以叠加,但含义不会叠加——比如 6755(4+2)同时开了 setuid 和 setgid,但普通文件极少需要两者都开。
-
4755→ 所有者有 setuid,组和其他人有 r-x -
2755→ 所属组有 setgid,所有人有 r-x(常用于共享目录的父目录) - 错误做法:
chmod 6755给一个普通工具程序,既没意义又增加攻击面;chmod 4777更危险——等同于“任何人执行都变 root”,严重违反最小权限原则
setuid/setgid 程序上线前必须检查的三件事
它们本质是权限提升通道,一旦程序有漏洞(比如路径注入、缓冲区溢出),攻击者就能直接拿到高权限。生产环境部署前务必确认:
- 程序是否真的必须用 root 或特定组权限?能否用
capabilities(如cap_net_bind_service)替代? - 二进制是否静态链接、无外部依赖?动态加载的库若被劫持(如 LD_PRELOAD),
setuid程序会直接执行恶意代码 - 程序是否清除了敏感环境变量?比如
setuid程序启动时应调用unsetenv("LD_LIBRARY_PATH")等,glibc 默认会忽略大多数环境变量,但并非全部
别只盯着权限位有没有加对,真正决定安全边界的,是那个二进制本身干了什么、信任了什么、又忽略了什么。










