linux用户用户组与ACL
使用者ID:UID与GID
在使用Linux的过程中,经常会遇到各种用户ID(user identifier, UID)和组ID(group identifier, GID),Linux也是通过对这些ID的管理实现的自主访问控制(discretionary access control, DAC)。
用户ID(英语:user identifier,一般缩写为User ID或UID),全称用户标识符,在类UNIX系统中是内核用来辨识用户的一个无符号整型数值,亦是UNIX文件系统与进程的必要组成部分之一。[1]
虽然我们登录Linux主机时使用的是账户,但是对于Linux系统而言,它只认识ID。而ID与账户的对应就记录在/etc/passwd
文件中。可以通过命令id
查看各个id与账户名的对应关系:
从上图中我们可以看到,我的用户名是wang
,它的UID是1000
,GID也是1000
。
UID范围
在不同系统中,UID值范围也有所不同,但一般来说UID是由一个16bit的无符号整数表示的,其范围在0-65535之间。
UID | 账户 |
---|---|
0 | root,超级用户的UID总为0 |
65535 | nobody,总是UID的最大值 |
1~999 | 一般约定是系统保留范围,由系统使用 |
1000~65534 | 一般用户UID |
UID与GID分类
值得注意的是,以下的分类都是针对进程而言的,只有进程才会有下述几种ID。
中文 | 英文 | 解释 |
---|---|---|
有效用户ID与有效组ID | Effective UID, EUID, Effective GID, GID | 在创建和访问文件时发挥作用。具体来说,创建文件时,系统内核将根据创建文件的进程的EUID与EGID设定文件的所有者/组属性,而在访问文件时,内核亦根据访问进程的EUID与EGID决定其能否访问文件。 |
真实用户ID与真实用户组 | Real UID, RUID, Real GID, RGID | 用于辨识进程的真正所有者,且会影响到进程发送信号的权限。 |
暂存用户ID | Saved UID, SUID | 特权权限运行的进程暂时需要做一些不需特权的操作时使用,这种情况下进程会暂时将自己的有效用户ID从特权用户(常为root)对应的UID变为某个非特权用户对应的UID,而后将原有的特权用户UID复制为SUID暂存;之后当进程完成不需特权的操作后,进程使用SUID的值重置EUID以重新获得特权。 |
文件系统用户ID | File System UID, FSUID | 在Linux中使用,且只用于对文件系统的访问权限控制,在没有明确设定的情况下与EUID相同(若FSUID为root的UID,则SUID、RUID与EUID必至少有一亦为root的UID),且EUID改变也会影响到FSUID。设立FSUID是为了允许程序(如NFS服务器)在不需获取向给定UID账户发送信号的情况下以给定UID的权限来限定自己的文件系统权限。 |
访问文件
举例而言,假设我要执行以下命令,sudo vim /etc/apt/sources.list
,我当前的用户是wang
,那么这个这个进程的RUID
就是1000
(对应wang
这个账户),而sudo
指使使用root
权限,因此该进程的EUID
就是0
(root
账户)。我们查看/etc/apt/sources.list
文件的所有者和所有组,它的所有者是root
,组是root
。因此我们必须使用sudo
进行提权,也即是修改进程的EUID
为0
,这样才能够访问/etc/apt/sources.list
文件,但是RUID
依然是1000
。
创建文件
再举例创建文件。如下图所示:
文件的所有组和所有者依然与进程的EUID和EGID指定,而非RUID和RGID。
父子进程
子进程继承了父进程所有的各种UID和GID。
权限控制
这里描述的权限控制是指Linux中基于用户和用户组以及r\w\x
权限的控制,其中r
表示可读,w
表示可写,x
表示可执行。
Linux一般把文件存取的身份分为三个类别:owner/group/others
,且三种身份都各有read/write/execute
权限。
查看/etc/shadow
的详细信息如下图所示:
分析如下:
权限 | 链接数 | 所有者 | 所有组 | 文件大小 | 文件最后被修改的时间 | 文件名 |
---|---|---|---|---|---|---|
-rw-r----- | 1 | root | shadow | 1.6K | May 9 2021 | /etc/shadow |
对权限进行详细分析如下,每个文件的权限都有10个字符表示,其中-
表示无对应权限,这十个字符可分为四组,第一组就是第一个字符;表示文件类型,第二组就是第2、3、4个字符,是所有者拥有的权限,依次是r/w/x
;第5、6、7个字符表示组权限,依次是r/w/x
;第8、9、10个字符表示其他人的权限,依次是r/w/x
。如果所在位置为-
,则表示无对应权限。
对应上述/etc/shadow
文件的权限为,所有者即root
拥有读写权限,组shadow
只有读权限,其他人没有任何权限。
rwx与421
在Linux系统中,可以使用chmod
命令来改变文件的权限,例如:sudo chmod 640 /etc/shadow
。这个含义就是将文件/etc/shadow
的所有者权限改为6即rw
;组权限改为4即r
;其他人权限改为0即无任何权限。之所以6表示rw
,4表示r
,这是因为Linux是通过位来表示权限的。
因为文件拥有三种不同的权限r/w/x
,Linux就使用3bit作为权限记录,如果是只读的那么就是100
,如果是只写的就是010
,如果是只可执行的就是001
,可读可写的呢就是110
啦。读者自行将二进制转换为十进制,就会发现6就表示110
,也就是可读可写不可执行的意思啦。
当然,这里描述的3bit权限位并不是实际上Linux的权限实现机制,而是为了读者方便理解记忆,数字与权限的对应关系。实际的权限记录比较复杂。
关于权限的一些问题
-
一个文件可有只写权限但是不可读吗?
答案是可以的,如下图所示。
-
一个文件不具有可执行权限就一定不可执行吗?有了可执行权限就一定可以执行吗?
答案是不一定。
-
目录的rwx
- 目录的只读访问不允许使用cd进入目录,必须要有执行的权限才能进入。
- 只有执行权限只能进入目录,不能看到目录下的内容,要想看到目录下的文件名和目录名,需要可读权限。
- 一个文件能不能被删除,主要看该文件所在的目录对用户是否具有写权限,如果目录对用户没有写权限,则该目录下的所有文件都不能被删除,文件所有者除外
- 目录的w位不设置,即使你拥有目录中某文件的w权限也不能写该文件
进程UID与文件权限类型的匹配
根据前文我们已经知道,对文件的访问和创建等操作需要检查的都是EUID
,而不是RUID
。即使RUID
是普通用户,而EUID
是root
则就拥有了对root
所能访问的所有文件的权限。对应/etc/shadow
我们就检查对应的root
权限是读写,因此该进程就可以对/etc/shadow
进行读写操作。如果,该进程的EUID
不是root
,但是是属于shadow
组的,那么就只有读权限,否则没有任何权限。
Set-UID提权[2]
在一个典型的计算机系统中,用户需要使用超级用户的权限来完成诸如修改密码的操作。一种方式是通过守护进程(Windows下成为服务)方式来实现,另一种方式是通过设置Set-UID
权限的方式来实现。
Set-UID程序和其他unix程序唯一的区别就在于他有一个特殊的标志位:Set-UID比特位。使用这个比特位的目的是告诉操作系统,当运行这个程序时应当与未设置该位的程序相区分。
我们在前文中提过,权限匹配是通过EUID
来实现的。对于非Set-UID程序而言,进程的EUID
是和RUID
一致的,当它被一个用户ID为5000的用户运行时,RUID
和EUID
都是5000。而当执行一个Set-UID程序时,RUID
和EUID
的值是不一样的,RUID
的值取决于执行该程序的用户ID,而EUID
则取决于Set-UID
程序文件的所有者。
设置Set-UID
提权测试
ACL(Access Control List)规则
前文所述的规则又称为UGO(user,group,others)规则,这套机制比较简单。在自主访问控制中,还有ACL规则,作为补充。在Linux系统中,ACL用于设定用户针对文件的权限。
ACL主要有两种命令进行控制,getfacl
和setfacl
。
# 例子源于https://blog.csdn.net/pwl999/article/details/110878563
[root@localhost ~]# useradd zhangsan
[root@localhost ~]# useradd lisi
[root@localhost ~]# useradd st
[root@localhost ~]# groupadd tgroup
// 添加需要试验的用户和用户组,省略设定密码的过程
[root@localhost ~]# mkdir /project #建立需要分配权限的目录
[root@localhost ~]# chown root:tgroup /project/
// 改变/project目录的属主和属组
[root@localhost ~]# chmod 770 /project/
// 指定/project目录的权限
[root@localhost ~]# ll -d /project/
drwxrwx--- 2 root tgroup 4096 1月19 04:21 /project/
// 查看一下权限,已经符合要求了
// 这时st学员来试听了,如何给她分配权限
[root@localhost ~]# setfacl -m u:st:rx /project/
// 给用户st赋予r-x权限,使用"u:用户名:权限" 格式
[root@localhost /]# cd /
[root@localhost /]# ll -d project/
drwxrwx---+ 3 root tgroup 4096 1月19 05:20 project/
// 使用ls-l査询时会发现,在权限位后面多了一个"+",表示此目录拥有ACL权限
[root@localhost /]# getfacl project
// 查看/prpject目录的ACL权限
#file: project <-文件名
#owner: root <-文件的属主
#group: tgroup <-文件的属组
user::rwx <-用户名栏是空的,说明是属主的权限
user:st:r-x <-用户st的权限
group::rwx <-组名栏是空的,说明是属组的权限
mask::rwx <-mask权限
other::--- <-其他人的权限
// 大家可以看到,st 用户既不是 /prpject 目录的属主、属组,也不是其他人,我们单独给 st 用户分配了 r-x 权限。这样分配权限太方便了,完全不用先辛苦地规划用户身份了。
推荐阅读
参考文献
杜文亮. 计算机安全导论:深度实践[M]. 高等教育出版社, 2020. ↩︎