3、Linux权限模型:用户与组、文件权限(rwx)、SUID/SGID、Capabilities机制

聊到Linux权限模型,我脑子里第一个蹦出来的词就是「精细」。Windows那边动不动就弹UAC,Linux这边呢?从用户到文件位,再到特殊权限位,最后到Capabilities,一层套一层。说白了,这就是一套「谁能在系统上干什么」的规则。

我个人习惯把Linux权限模型拆成四个层次来讲:用户与组、文件权限(rwx)、SUID/SGID、Capabilities。你把这四个吃透了,提权漏洞在你眼里就跟透明的一样。

3.1 用户与组:权限的起点

Linux里,每个进程都有一个UID(用户ID)和GID(组ID)。这是内核判断「你是谁」的唯一凭证。你想想看,系统里所有操作,最终都要落到某个用户头上。

用户分三种:

  • root(UID=0):上帝模式,想干嘛干嘛。我见过不少新手直接拿root跑服务,结果被提权漏洞一锅端。
  • 系统用户(UID 1-999):给daemon、服务用的。比如nginx、mysql都有自己的用户。嗯,这里要注意:这些用户通常没有登录shell。
  • 普通用户(UID >= 1000):你我日常用的。

组的作用呢?说白了就是「权限打包」。你把一堆用户塞进一个组,然后给这个组赋予某个文件的权限,省得一个一个配。

提权视角:渗透测试时,我第一件事就是跑 id 和 groups。看看当前用户在哪些组里。比如你在 docker 组,那恭喜你,提权路径基本就打开了。

3.2 文件权限(rwx):最基础的防线

每个文件或目录,都有三组权限位:所有者(owner)、所属组(group)、其他人(others)。每组三个位:r(读)、w(写)、x(执行)。

用 ls -l 看一眼:

-rwxr-xr-- 1 root root 1024 Jan 1 12:00 test.sh

这串字符怎么拆?

  • 第一个字符:文件类型(-普通文件,d目录,l链接)
  • 第2-4位:owner权限(rwx)
  • 第5-7位:group权限(r-x)
  • 第8-10位:others权限(r--)

数字表示法更常用:r=4, w=2, x=1。上面的 rwxr-xr-- 就是 754。

我的经验:目录的x权限和文件的x权限不一样。目录的x权限代表「能否进入该目录」。我曾经遇到一个案例,某个目录权限是 rw-rw-rw-,没有x,结果所有用户都进不去,但文件内容却能通过绝对路径读取。嗯,这算是个冷门知识点。

3.3 SUID/SGID:危险的「借权限」机制

SUID和SGID,是我在渗透测试中最喜欢碰的东西。为什么?因为它们允许普通用户以文件所有者的身份执行程序。

看个例子:

-rwsr-xr-x 1 root root 34888 Jan 1 12:00 /usr/bin/passwd

注意owner权限位的 s。这就是SUID位。普通用户执行 passwd 时,有效UID会临时变成root。这样才能修改 /etc/shadow。

SGID同理,只不过借的是组的权限。目录上设SGID还有个特殊效果:在该目录下新建的文件,所属组自动继承父目录的组。

避坑指南:我曾经在某个客户的内网里,发现一个 /usr/bin/find 被设置了SUID。攻击者直接 find . -exec /bin/sh \; 就拿到了root shell。所以,任何非必要的SUID二进制文件,都是安全隐患。

怎么找SUID文件?

find / -perm -4000 -type f 2>/dev/null

SGID同理,把 4000 换成 2000 就行。

3.4 Capabilities机制:细粒度的权限控制

SUID有个大问题:要么全有,要么全无。你给一个程序SUID,它就拥有了root的全部能力。这太粗暴了。

Capabilities机制就是为了解决这个问题的。它把root的超级权限拆成了几十个小单元。比如:

Capability 作用
CAP_NET_BIND_SERVICE 允许绑定到1024以下端口
CAP_DAC_OVERRIDE 绕过文件权限检查(相当于root的读写能力)
CAP_SYS_ADMIN 超级管理权限,相当于半个root
CAP_SETUID 允许修改UID(提权常用)

查看一个二进制文件的Capabilities:

getcap /usr/bin/ping
# 输出:/usr/bin/ping = cap_net_raw+ep

这里的 +ep 表示Effective和Permitted位都设置了。说白了就是「这个能力生效了」。

提权视角:我经常用 getcap -r / 2>/dev/null 来扫描全系统。如果发现 python 或 perl 被设置了 cap_setuid+ep,那基本就是一条提权捷径。比如:

python -c 'import os; os.setuid(0); os.system("/bin/sh")'

瞬间变root。

我的建议:生产环境里,能用Capabilities就别用SUID。比如nginx需要绑定80端口,给它 cap_net_bind_service+ep 就够了,完全没必要给SUID。这样即使nginx被攻破,攻击者也拿不到root权限。

3.5 实战中的权限检查清单

每次做渗透测试,我脑子里都有一张清单。分享给你:

  1. 查用户身份:id、whoami、groups
  2. 查SUID/SGID:find / -perm -4000 -type f
  3. 查Capabilities:getcap -r / 2>/dev/null
  4. 查可写文件:find / -writable -type f 2>/dev/null
  5. 查历史命令:cat ~/.bash_history(经常能发现密码)

你想想看,如果某个普通用户能写 /etc/passwd,或者某个脚本被设置了SUID,那提权就是分分钟的事。

嗯,最后说一句:权限模型不是死的。你理解了它的设计哲学——「最小权限原则」,就能在攻防中游刃有余。我见过太多因为一个SUID位没处理好,导致整个内网沦陷的案例了。别让这种事发生在你身上。