Linux 权限管理与访问控制详解(1)——基本概念和 DAC

Linux系统的权限管理与访问控制,大体可以分为基础与高级两部分,基础机制即传统的UGO+RWX/ACL,高级的即为SELinux,本文将按照从基础到高级的顺序讲解,先从系统的安全模型说起。
另,本文中所有例子均是在 CentOS7 中运行的,不同系统运行结果可能有所不同。

1. 安全模型概述

操作系统的权限管理与访问控制机制,遵从一定的 安全模型 或者 安全机制 ,常见的安全模型有 BLP安全模型RBAC安全模型多级别安全机制 。Linux 系统也不例外,其基础的权限管理与访问控制机制和加强的 ACL 机制、SELinux,都对这些安全模型与安全机制有所实现。

1.1 BLP安全模型


BLP(Bell & Lapadula)安全模型是由David Bell 和 Leonard La Padula 在1973年模拟军事安全策略创建的计算机系统安全模型, 74年改进, 76年首次实现于 Multics 操作系统。该安全模型是一个状态机模型,有一系列错综复杂的数学证明来保证其安全性的结果;它是定义多级安全性的基础,被视作基本安全公理

该模型将信息系统中的实体分为两部分:主体(Subject)和客体(Object)。实时操作的成为主体,如用户进程;被操作的对象则成为客体,如文件数据库等。对主体和客体来说,有两种最重要的安全控制方法:自主存取控制强制存取控制

  • DAC(Discretionary Access Control,自主访问控制)。DAC 机制就是指对象的拥有者可以任意修改或授予此对象相应的权限。从主体和客体的角度来说,就是主体对其拥有的客体,有权决定自己和其他主体对该客体应具有怎样的访问权限。传统的Linux、Windows都采用这种机制,比如某用户对于其所有的文件或目录,可以随意设定UGO(即:本用户、本用户组、其他用户)对该文件的RWX(即:读、写、执行)权限,下文详解;
  • MAC(Mandatory Access Control,强制访问控制)。MAC机制是指系统不再允许对象的拥有者随意修改或授予此对象相应的权限,而是通过强制的方式为每个对象一一授予权限,SELinux即采用这种机制。该机制主要通过安全级来实现,下文详解。

1.2 RBAC安全模型


RBAC(Role Based Access Control,基于角色的访问控制)模型是一种强制访问控制机制。在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相应的角色,用户可以很容易地从一个角色被指派到另一个角色。角色可依新的需求和系统的合并而赋予新的权限,而权限也可根据需要而从某角色中回收。角色与权限的关系可以建立起来以囊括更广泛的客观情况。

RBAC 支持三个著名的安全原则:最小权限原则,责任分离原则和数据抽象原则

  • 最小权限原则之所以被RBAC所支持,是因为RBAC可以将其角色配置成其完成任务所需要的最小的权限集;
  • 责任分离原则可以通过调用相互独立的角色来共同完成一个任务,比如要求一个计帐员和财务管理员一起参与过帐;
  • 数据抽象可以通过权限的抽象来体现,如财务操作用借款、存款等抽象权限,而不用操作系统提供的典型的读、写、执行权限。然而这些原则必须通过RBAC各部件的详细配置才能得以体现。

SELinux 部分实现了RBAC的机制,SELinux 上下文中的 Role 元素,即是基于 RBAC 设计的,下文详解。

1.3 多级别安全机制


MLS(Multi-Level Security,多级别安全)机制给用户提供了可以用不同等级的安全角色来访问系统。例如,MLS安全分级从低到高为ConfidentialSecretTOP SecretIndividuals,不同级别可以访问不同分类的信息,低级别无权访问高级别信息。

SELinux 中,客体上的安全级别称为 分级(Classifications),主体上的安全级别称为 Clearances。SELinux上下文元素中的 安全级别,即是基于此安全机制而设计。SELinux 中的对象上下文,必须至少有一个安全级别(它由单个敏感度和0个或多个范围组成),但可以包括两个安全级别,这两个安全级别分别叫做 (或进程趋势,即安全级别下限) 或 (或进程间隙,即安全级别上限),如果安全级别丢失,它会被认为与低安全级别的值相同(最常见的情况)。实际上,对于客体和进程而言,低和高安全级别通常都是相同的,通常用于进程的级别范围被认为是受信任的主体(即进程信任降级信息)或多层客体,如一个目录,它又包括了不同安全级别的客体。

2. 自主访问控制

Linux中实现的自主访问控制(DAC)机制主要包括基础的 UGO+RWX 和加强的 ACL(Access Control List)

2.1 UGO+RWX 相关


该机制的思想是通过对用户(组)及其所属进程对文件和目录的访问赋予一定的权限,来实现基本的权限管理与访问控制。

Linux为每个文件都分配了一个文件所有者,称为文件主,并赋予文件主惟一的注册名。对文件的控制取决于文件主或超级用户(root)。文件或目录的创建者对创建的文件或目录拥有特别使用权。

文件的所有关系是可以改变的,可以将文件或目录的所有权转让给其它用户,但只有文件主或root用户才有权改变文件的所有关系。文件的所有权的标志是用户ID(UID),这正是DAC机制的核心概念。

2.1.1 UGO+RWX表示

Linux系统中的每个文件和目录(客体)都有相应的访问权限,通过其确定谁(主体)可以通过何种方式对文件/目录进行访问和操作。文件/目录(客体)的访问权限分为三种:执行。该机制限制三种不同的主体文件所有者同组用户其他用户

每个文件或目录的访问权限都有三组,每组用三位表示,分别为文件属主的读、写和执行三种权限。当用Shell命令 ls -l 显示文件或目录的详细信息时,最左边的一排为文件的访问权限。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
➜ ls -l /var
drwxr-xr-x. 2 root root 18 10月 16 17:25 account
drwxr-xr-x. 2 root root 6 6月 10 2014 adm
drwxr-xr-x. 11 root root 4096 12月 12 14:32 cache
drwxr-xr-x. 2 root root 6 10月 23 19:27 crash
drwxr-xr-x. 3 root root 32 12月 10 14:54 db
drwxr-xr-x. 3 root root 17 10月 16 17:25 empty
drwxr-xr-x. 2 root root 6 6月 10 2014 games
drwxr-xr-x. 2 root root 6 6月 10 2014 gopher
-rw-r--r--. 1 root root 25 12月 12 15:01 info.php
drwxr-xr-x. 3 root root 17 10月 16 17:21 kerberos
drwxr-xr-x. 40 root root 4096 12月 17 03:20 lib
drwxr-xr-x. 2 root root 6 6月 10 2014 local
lrwxrwxrwx. 1 root root 11 10月 16 17:19 lock -> ../run/lock
drwxr-xr-x. 13 root root 4096 12月 15 14:50 log
lrwxrwxrwx. 1 root root 10 10月 16 17:19 mail -> spool/mail
drwxr-xr-x. 2 root root 6 6月 10 2014 nis
drwxr-xr-x. 2 root root 6 6月 10 2014 opt
drwxr-xr-x. 2 root root 6 6月 10 2014 preserve
lrwxrwxrwx. 1 root root 6 10月 16 17:19 run -> ../run
drwxr-xr-x. 10 root root 4096 10月 16 17:25 spool
drwxrwxrwt. 7 root root 4096 12月 15 14:52 tmp
drwxr-xr-x. 3 root root 16 10月 16 17:23 var
drwxr-xr-x. 4 root root 31 12月 12 15:03 www
drwxr-xr-x. 2 root root 6 6月 10 2014 yp

权限列共有 10 个字符,第一个字符为文件类型,后面九个分为三组:第一组为 U(User) ,即文件属主对应的权限;第二组为 G(Group),即同组用户对应的权限;第三组为 O(Others),即其他用户对应的权限。每个字符的意义可用下图描述:

图解文件权限

NOTE:
上面例子中,权限列的第一个字符(文件类型),-代表普通文件;l代表链接文件;d代表目录文件。

另,Linux中,文件与目录的权限有所区别,如下所示:

文件 目录
R(可读) 读取文件内容 读包含在目录中的文件名称
W(可写) 对文件内容进行编辑 可以写信息到目录中,即可以创建、删除文件、移动文件等操作
X(可执行) 作为执行文件执行 可以进入目录;可以搜索(能用该目录名称作为路径名去访问它所包含的文件和子目录)

举例说明

  1. 对文件有 w 权限不能删除文件,需要对文件所在的目录有 w 权限;
  2. 对目录有 w 权限不能 cd 进入目录,需要对目录有 x 权限;
  3. 对目录有 x 权限,只有在知道文件名并且有 r 权限的时候才能访问目录下的文件;
  4. 对目录必须有 x 权限才能 cd 进入到目录,必须有 rx 权限才能使用 ls 列出目录清单
  5. 对目录有 w 权限,可以对目录中的任何文件或子目录进行创建、删除或修改操作,即使该文件或目录的所有者是其它用户也是如此。

2.1.2 权限管理

chmod

chmod命令可以修改文件或目录的权限,但有两种方式来修改,一种是字母权限设定法,另一种是数字权限设定法。用字母权限设定法时,该命令的格式通常是:

1
chmod [who] [+|-|=] [mode] [file/dir]

其中,操作对象 who 表示将权限赋予的主体[+|-|=]部分是权限的操作符;[mode]即为三个标志位表示的权限。

who可以是下列字母中的单个字母或多个字母的组合:

u: 表示 用户(User),即文件属主;
g: 表示 同组用户(Group),即与文件属主在同一用户组的用户;
o: 表示 其他用户(Others)
a: 表示 所有用户(All)。此为系统默认值

权限操作符解释如下:

+ : 添加某权限;
-:取消某权限;
= : 覆盖原权限。

mode 所表示的权限可用下列字母的任意组合:

r: 可读;
w: 可写;
x: 可执行(只有目标文件对某些用户是可执行的或该文件为目录时才可追加X属性);
s: 在文件执行时,把进程的属主或组ID置为该文件的文件属主。方式 u+s 设置文件的用户ID位,g+s设置组ID位;
t: 将程序的文本保存到交换设备上;
u: 与文件属主拥有同样的权限;
g: 与文件属主同组用户拥有同样的权限;
o: 与其他用户拥有同样的权限。


数字权限设定法

chmod命令用这种方式设定文件/目录权限是的格式通常为:

1
chmod [digital_mode] [file/dir]

这种方法与字幕权限设定法在功能上是等价的,不过更加简便:将上述字母表示的权限位映射为数字,并将3组数字组合起来。映射关系为:

r —-> 4
w —-> 2
x —-> 1
- —-> 0 (空权限,即无此权限)

所以数字属性的格式为 3 个 0~7 的八进制数,其顺序是 U/G/O

对于两种权限表示方法,统一给出一组示例如下:

-rw------- (600) 只有所有者才有读和写的权限
-rw-r--r-- (644) 只有所有者才有读和写的权限,组群和其他人只有读的权限
-rwx------ (700) 只有所有者才有读,写,执行的权限
-rwxr-xr-x (755) 只有所有者才有读,写,执行的权限,组群和其他人只有读和执行的权限
-rwx--x--x (711) 只有所有者才有读,写,执行的权限,组群和其他人只有执行的权限
-rw-rw-rw- (666) 每个人都有读写的权限
-rwxrwxrwx (777) 每个人都有读写和执行的权限

NOTE:
使用 chmod 命令还可以将某个目录下的所有文件、子目录及子目录下的所有文件递归地设置为统一的权限,只需要加一个-R参数即可。


chown

该命令可以改变文件的属主。示例如下:

1
2
3
4
5
6
➜ touch test.txt
➜ ls -l
-rw-r--r--. 1 root root 0 12月 17 17:20 test.txt
➜ chown jiayu test.txt
➜ ls -l
-rw-r--r--. 1 jiayu root 0 12月 17 17:20 test.txt

其实也可以修改文件所属的用户组,示例如下:

1
2
3
4
5
➜ ls -l
-rw-r--r--. 1 jiayu jiayu 0 12月 17 17:20 test.txt
➜ chown :root test.txt
➜ ls -l
-rw-r--r--. 1 jiayu root 0 12月 17 17:20 test.txt

还可以同时修改文件的属主和所属用户组

1
2
3
4
5
➜ ls -l
-rw-r--r--. 1 jiayu jiayu 0 12月 17 17:20 test.txt
➜ chown root:root test.txt
➜ ls -l
-rw-r--r--. 1 root root 0 12月 17 17:20 test.txt

该命令也可以用-R参数进行递归操作。


chgrp

该命令只可以修改文件所属的用户组

1
2
3
4
5
➜ ls -l
-rw-r--r--. 1 root root 0 12月 17 17:20 test.txt
➜ chgrp jiayu test.txt
➜ ls -l
-rw-r--r--. 1 root jiayu 0 12月 17 17:20 test.txt

该命令也可以用-R参数进行递归操作。


umask

umask又叫权限掩码,其功能是设定新建文件/目录的默认权限。它与 chmod 配套,总共为4位(gid/uid,属主,组权,其它用户的权限),不过通常用到的是后3个,例如你用 chmod 755 file(此时这文件的权限是属主读(4)+写(2)+执行(1),同组的和其它用户有读写权限)。当新文件被创建时,其最初的权限由文件创建掩码决定。用户每次注册进入系统时,umask命令都被执行,并自动设置掩码 mode 来限制新文件的权限。用户可以通过再次执行umask来改变默认值,新的权限将会把旧的覆盖掉。

默认情况下的 umask值是 022(可以用umask命令查看),此时你建立的文件默认权限是755(即777-022)。

利用umask命令可以指定哪些权限将在新文件的默认权限中被删除。例如,可以使用下面的命令创建掩码,取消组用户的写权限以及其他用户的读、写和执行权限: umask u=,g=w,o=rwx

执行该命令以后,下面所建新文件的文件主权限未作任何改变,而组用户没有写权限,其它用户的所有权限都被取消。

umask命令和chmod命令中,操作符=的作用恰恰相反。在chmod中,利用它来设置指定的权限,而其余权限都被取消;但是在umask命令中,它将在原有权限的基础上把指定的权限删除

不能直接利用umask创建一个可执行的文件,用户只能在其后利用chmod命令使它具有执行权限。假设执行了下面命令:
umask u=,g=w,o=rwx
虽然在命令行中,文件主和组用户的执行权限没有被删去,但默认的文件权限还 是640(即rw-r—–),而不是750(rwxr-x—)。但是,如果创建的是目录,或者通过编译程序创建一个可执行文件,将不受此限制。 在这种情况下,文件的执行权限会被设置。

此外,也可以使用八进制数值来设置mode。在umask中所指定的权限 表示要删除的权限,所以,如果一个文件原来的初始权限是777,那么执行命令umask 022以后, 那么该文件的权限将变为`755;如果该文件原来的初始权限是666, 那么该文件的权限将变为644


特殊访问模式及粘滞位:setuid/setgid/sticky bit

Linux中,非root用户可以使用passwd命令修改自己的密码,这是合理的设置,但是有个小问题:该命令位置是/bin/passwd,其详细的权限为:

1
2
➜ ls -l /bin/passwd
-rwsr-xr-x. 1 root root 27832 6月 10 2014 /bin/passwd

可以看到其属主为root用户,所属用户组也为root组,那为何非root用户也可以调用此命令呢?
问题出在 本用户权限 处的s权限位,可以看到它处在原属于可执行权限x的位置。这个s就是setuid位的标识。setuid位表明该文件在执行阶段具有文件属主的权限。所以非root用户也能调用这个本属于root用户的/bin/passwd命令来执行修改密码的操作。

与其类似的还有下面两个标志位:

  • setgid:该权限只对目录有效. 目录被设置该位后, 任何用户在此目录下创建的文件都具有和该目录所属的组相同的组;
  • sticky bit: 粘滞位,该位可以理解为防删除位. 一个文件是否可以被某用户删除, 主要取决于该文件所属的组是否对该用户具有写权限. 如果没有写权限, 则这个目录下的所有文件都不能被删除, 同时也不能添加新的文件. 如果希望用户能够添加文件但同时不能删除文件, 则可以对文件使用sticky bit位. 设置该位后, 就算用户对目录具有写权限, 也不能删除该文件.

这三个特殊权限位也可以用chmod命令来操作,同样也分字幕权限设定和数字权限设定两种方式。
文字设定法:

chmod u+s file:为文件 file 加上 setuid 标志位;
chmod g+s dir:为目录 dir 加上 setgid 标志位;
chmod o+t file:为文件 file 加上 sticky 标志。

数字权限设定法:
其实本身linux 下权限是有四个数字的,我们常用的 chmod 777 xxx 其实默认是 chmod 0777 xxx

而第一位的 0 也有 4/2/1 三种组合,分别代表

setuid 的二进制串为:100,换算十进制为:4,若该位有效,显示为s,在原来本用户权限x标志位上;
setgid 的二进制串为:010,换算十进制:2,若该位有效,显示为s,在原来同组用户权限x标志位上;
sticky bit 二进制串:001,换算十进制:1,若该位有效,显示为t,在原来其他用户权限x标志位上。

显示的示例如下:

r-srw-r– : 表示有 setuid 标志;
rwxrwsrw- : 表示有 setgid 标志;
rwxrw-rwt : 表示有 sticky 标志。

2.2 ACL相关

2.2.1 为什么要用 ACL


在Linux下,对一个文件(或者资源)可以进行操作的对象被分为三类: U(文件的拥有者), G(文件所属用户组), O(其他);而对于每一类别又分别定义了R(可读),W(可写)和 X(可执行)三种权限 (这里不讨论SUID, SGID以及Sticky bit的设置)。此即上述UGO+RWX的传统权限管理与访问控制机制。
通过ls -l命令就我们就可以列出一个文件的权限:

1
2
➜ ls -l
-rw-rw---- 1 leonard admin 0 Jul 3 20:12 test.txt

在这里说明了对于test.txt这个文件leonard用户(由于是file owner)拥有权限. 所有属于admin组的用户(group)拥有读和写权限. 其他任何用户(other)对于文件没有任何的权限。
如果我们现在希望john这个用户也可以对test.txt文件进行读写操作.大概会想到以下几种办法 (这里假设john不属于admin用户组):

  1. 给文件的other类别增加读和写权限. 这样由于john会被归为other类别,那么他也将拥有读写的权限;
  2. john加入到admin 用户组. 那么john会被归为admin类别,那么他将拥有读写的权限;
  3. 设置sudo, 使john能够以leonard的身份对test.txt进行操作,从而获得读写权限。

第一种做法的问题在于所有用户都将对test.txt拥有读写操作,显然这种做法不可取;
第二种做法的问题在于john被赋予了过多的权限.所有属于admin组的文件,john都可以拥有其等同的权限了;
第三种做法虽然可以达到只限定john用户一人拥有对test.txt文件的读写权限.但是需要对sudoers文件进行严格的格式控制. 而且当文件数量和用户很多的时候,这种方法就相当地不灵活了。

上述方案都不太理想,其实问题就出在 Linux 的 UGO+RWX 权限管理机制里面,对于other的定义过于广泛,以至于很难把权限限定于一个不属于file ownergroup的用户身上。ACL(Access Control List,访问控制列表) 就是用来帮助我们解决这个问题的。

简单地来说ACL就是可以设置特定用户或者用户组对于一个文件的操作权限. 需要掌握的命令也只有三个: getfacl, setfacl, chacl

2.2.2 ACL安装

  1. Debian & Ubuntu 下安装ACL:

    1
    ➜ apt-get install acl
  2. RHEL & CentOS & Fedora 下安装ACL :

    1
    ➜ yum install acl

重新挂载分区(如果分区不支持ACL,需要以ACL的属性重新挂载)

1
➜ mount -o remount,rw,acl /dev/sda3

分区在不支持acl的情况下getfacl可以工作,但是setfacl不能够工作的。

2.2.3 ACL机制简介

ACL 是由一系列的 Access Entry 所组成的. 每一条 Access Entry 定义了特定的类别可以对文件拥有的操作权限.,Access Entry 有三个组成部分: Entry tag type, qualifier (optional), permission

最重要的Entry tag type, 它有以下几个类型:

  • ACL_USER_OBJ : 相当于Linux里权限位U
  • ACL_USER : 定义了额外的用户可以对此文件拥有的权限;
  • ACL_GROUP_OBJ : 相当于Linux里权限位G
  • ACL_GROUP : 定义了额外的组可以对此文件拥有的权限;
  • ACL_MASK : 定义了ACL_USER, ACL_GROUP_OBJACL_GROUP的最大权限;
  • ACL_OTHER : 相当于Linux里权限位O

举例说明一下,getfacl命令来查看一个定义好了的ACL文件代码:

1
2
3
4
5
6
7
8
9
10
➜ getfacl ./test.txt
# file: test.txt
# owner: leonard
# group: admin
user::rw-
user:john:rw-
group::rw-
group:dev:r--
mask::rw-
other::r--

前面三个以#开头的定义了文件名,file,ownergroup, 这些只是辅助信息,没有太大的作用,可以用 --omit-header参数来省略掉:

user::rw- : 定义了ACL_USER_OBJ, 说明file owner拥有读写权限;
user:john:rw- : 定义了ACL_USER,这样用户john就拥有了对文件的读写权限,实现了我们一开始要达到的目的;
group::rw- : 定义了ACL_GROUP_OBJ,说明文件的group拥有读写权限;
group:dev:r– : 定义了ACL_GROUP,使得dev组拥有了对文件的读权限;
mask::rw- : 定义了ACL_MASK的权限为读和写;
other::r– : 定义了ACL_OTHER的权限为读。

从这里可以看出ACL提供了定义特定用户和用户组相应权限的功能。关于如何设定一个文件或目录的ACL权限,以及 ACL_MASK怎么使用,Default ACL如何使用等信息,可参考参《Linux ACL管理详解》。

3. 参考资料

  1. Linux文件或目录的读/写/执行权限
  2. chmod 设置目录或文件的访问权限
  3. 深入理解SetUID
  4. chmod命令高级篇–SetUID与SetGID标识位
  5. Linux ACL管理详解
  6. 在 Linux 使用 POSIX ACL 控制档案的存取