安全秘笈第二式——不安全的特殊权限和强制访问控制(MAC)
在DAC的机制中,不管是所有权加权限的管理办法,还是文件系统访问控制列表(facl),都是非常强大的访问控制机制,均可以对文件资源进行比较有效的访问控制。但DAC的自主性太强,可以说文件资源的安全在很大的程度上取决于使用者个人的意志,因此这种安全似乎就被主观化了。尤其是对于root用户而言,不管是权限和所有权的限制,还是facl的管理控制,都仅仅能够限制root的误操作而已。
在CentOS或RHEL系统中,每一个服务都需要以守护进程的方式运行起来并在后台监听指定的套接字,比方说:实现DNS服务的bind软件需要一个名为named系统用户启动名为named的守护进程;MySQL服务的启动也需要一个名为mysql的系统用户来启动一个名为mysqld的守护进程,等等。如果类似这样的网络服务的TCP或UDP的会话被攻击者劫持,那么攻击者就可以冒用这些系统用户的身份。有人会说,没有什么大不了的嘛,这些连系统都无法登录的系统用户被劫持了也不会有什么危险啊。但是请记住,在CentOS或RHEL的文件系统中有三个特殊权限,即:SUID、SGID和Sticky,其中SGID如果设置在目录上,则在该目录中创建的所以新文件的属组都是从该目录上继承的该目录的属组;如果设置在文件上,则在该目录中如果包含了可执行文件的话,无论是谁发起的执行进程,改进程的属组都是该目录的属组。Sticky也被翻译为“粘滞位”,只能设置在目录上。凡是被设置了粘滞位的目录,即便用户对该目录有所以的rwx的权限,也只能管理属主是其自身的那些文件,禁止了对属主不为自己的所以文件的修改和删除等写操作。可以说这两个特殊权限还是有一定的方便管理和安全保证作用的。
但是,SUID可是一把非常锋利的双刃剑,用好了,方便管理所向披靡;用不好,那可就是为他人做嫁衣而置自己于死地了。
为什么这么说呢?我们一起来分析一下SUID这个特殊权限位。SUID只能设置在二进制文件上,也就是在CentOS或RHEL中的具有ELF可执行权限的二进制文件,我们所编写的shell脚本一般是无法设置这个权限的,这是一个很严格的限制。一旦在可执行的二进制文件上添加了SUID,则所有用户在执行这个程序以后,都是以这个文件的所有者的身份来进行。现在大家明白了么?在CentOS或RHEL中,根文件系统下的文件的属主绝大多数都是root,包括那些二进制文件,所以不管你是什么用户,一旦执行了设置了SUID的二进制文件,也就意味着能够以root用户的身份操纵这个二进制文件去访问所有属主为root的文件了。所以即便是无法登录到系统的系统用户,一旦因为这样的问题而获得root的身份之后,仍然可以为所欲为的。
比如说,CentOS或RHEL中的DNS服务在运行过程中,其进程会话被劫持,也就意味着攻击者已经获得了named用户的身份。此时,如果攻击者以named用户的身份,在/var/named/slaves目录中上传了一个带有SUID权限的二进制程序vim,这个vim跟系统中的vim是一模一样的,所需要的库也是一模一样的。于是,每次执行这个vim文件来查看系统中的其他文本文件的时候,都好像是root用户在执行这样的操作,那么接下来修改将文件修改成什么样子其实就看攻击者的心情了。
说了这么多,其实主要是想说明这样一个问题:传统的DAC固然能够有效的控制文件的访问,但是无法解决因为SUID等因素导致的root身份盗用带来的问题。
鉴于此,在防止root用户对资源误操作和权限滥用的问题上,就迫切需要行之有效的管理办法或解决方案,以增强系统的安全性和资源访问的安全性。
人们首先在文件系统上打起了主意。文件系统中被引入了一个新的挂载选项——nosuid,该选项不允许非root用户向文件系统中复制带有SUID的权限的文件,从而在一定程度上保证了root身份盗用的问题。但是这仍然是治标不治本的方法,最最核心的问题是root权限太大的问题。
于是,人们提出了强制访问控制(Mandatory Access Control——MAC,以下简称MAC)这一安全概念。MAC最早主要用于军方的应用中,通常与DAC结合使用。
首先让我们来了解两个至关重要的术语:
主体:
通常指用户,或由用户发起运行的进程或用户正在使用的设备。主体主动发起对资源的访问,它是系统中信息流的启动者。
客体:
通常是指信息的载体或从其他主体或客体接收信息的实体。主体有时也会成为访问或受控的对象,如一个主体可以向另一个主体授权,一个进程可能控制几个子进程等等,这时受控的主体或子进程也通常被认为是一种客体。
MAC是利用策略将访问控制规则“强加”给访问主体的,即系统强制主体服从访问控制策略。MAC的主要作用对象是所有主体及其所操作的客体(如:进程、文件等)。MAC为这些主体及其所操作的客体提供安全标记,这些标记是实施强制访问控制的依据。
系统通过比较主体和客体的安全标记来判断一个主体是否能够访问其要操作的客体。用户发起的进程无法改变其自身及其它客体的安全标记,利用这样的机制,系统可以比较有效地防止特洛伊木马攻击以及root身份冒用或盗用等安全威胁。
MAC一般与DAC共同使用,两种访问控制机制的过滤结果将累积,以此来达到更佳的访问控制效果。也就是说,一个主体只有通过了DAC限制检查与MAC限制检查的双重过滤装置之后,才能真正访问某个客体。一方面,用户可以利用DAC来防范其它用户对那些所有权归属于自己的客体的攻击;另一方面,由于用户不能直接改变MAC属性,所以MAC提供了一个不可逾越的、更强的安全保护层以防止其它用户偶然或故意地滥用DAC。
MAC的强制访问策略为每个用户、进程及文件赋于一个安全访问级别,即:
最高秘密级(Top Secret,一般标记为T);
秘密级(Secret,一般标记为S);
机密级(Confidential,一般标记为C);
无级别级(Unclassified,一般标记为U);
其级别为从高到低依次为:T>S>C>U,系统根据主体和客体的敏感标记来决定访问模式。通常情况下,访问模式包括:
下读(read down):用户级别大于文件级别的读操作;
上写(Write up):用户级别小于文件级别的写操作;
下写(Write down):用户级别大于文件级别的写操作;
上读(read up):用户级别小于文件级别的读操作;
依据Bell-Lapadula安全模型所制定的原则是:利用不上读/不下写来保证数据的保密性。即不允许低访问级别的用户读高访问级别的信息,也不允许高访问级别的信息写入低访问级别区域,禁止信息从高访问级别流向低访问级别。MAC通过这种梯度安全标签实现信息的单向流通。
依据Biba安全模型所制定的原则是:利用不下读/不上写来保证数据的完整性。在实际应用中,完整性保护主要是为了避免应用程序修改某些重要的系统程序或系统数据库。
可能大家觉得我这里说的是天花乱坠,真的有这么神奇么?答案是肯定的。在MAC理论出现后不久,很多人和团体本着这个目的开始研究用于实现强制访问控制的安全模块。美国国家安全局(NSA,The National Security Agency)和(SCC,Secure Computing Corporation)在Linux社区的帮助下开发了这样一个强制访问控制的安全模块,在2000年时,以GNU GPL发布,Linux内核2.6版本后集成在内核中。这个安全模块通常被人们称为SELinux,即(Secure Enhanced Linux,安全增强的Linux)。
SELinux有三种工作模式:
Enforcing——强制模式
表示SELinux正在运行,已经开始执行策略中的规则,并且开始正确的限制domain/type了
Permissive——警告模式(运用排错中)
表示SELinux正在运行,不过仅会有警告信息并不会实际限制domain/type的存取。这种模式作为SELinux的debug之用
Disabled——禁用模式
表示SELinux已经关闭,SELinux并没有实际运行。
注意:从强制模式切换到禁用模式,或者禁用模式切换到强制模式,都必须等到计算机下次启动的时候才会生效。但是强制模式和警告模式在切换时,立刻生效。
SELinux有四种可选的策略结果集:
strict:这种策略结果集主要应用于RHEL5和Centos5,系统中的每个进程都受到SELinux的控制。
targeted: 这种策略结果集主要用来保护常见的网络服务,SELinux仅对有限进程进行控制,也只监控容易被入侵的进程,RHEL4中只保护13个服务,RHEL5保护88个服务。
minimum:这种策略结果集主要应用于Centos7,这是修改过的targeted,只对选择的网络服务进行限制和保护。
mls: 这种策略结果集主要提供MLS(多级安全)机制的安全性保证。
在/etc/selinux/config文件中定义了该操作系统中SELinux的工作模式以及SELinux所支持使用的策略结果集:
CentOS5.11系统:
# This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - SELinux is fully disabled. SELINUX=enforcing # SELINUXTYPE= type of policy in use. Possible values are: # targeted - Only targeted network daemons are protected. # strict - Full SELinux protection. SELINUXTYPE=targeted
CentOS6.8系统中:
# This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=enforcing # SELINUXTYPE= can take one of these two values: # targeted - Targeted processes are protected, # mls - Multi Level Security protection. SELINUXTYPE=targeted
CentOS7.2系统中:
# This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=enforcing # SELINUXTYPE= can take one of three two values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted
通过对比,我们可以发现,在不同的CentOS的发行版本中,如果我们按照默认的配置安装系统,那么SELinux在系统中就是工作在强制模式(enforcing)下;另外,虽然各个发行版CentOS所支持的SELinux的策略结果集的种类和数量不尽相同,但是默认的策略结果集都是targeted。因为strict策略结果集过于严格而显得不灵活,minimum策略结果集和mls策略结果集稳定性不足,所以均未加以应用。
只要SELinux的工作模式是Enforcing,根据SELinux所选择的策略结果集,给所有文件和进程都打上安全标签,即:安全上下文(security context)。这一行为是在将SELinux的模式由disabled模式更改为enforcing模式后的第一次启动时完成的。
安全上下文由五个元素组成:user:role:type:sensitivity:category。
user:指示登录系统的用户类型,如:root,user_u,system_u,多数本地进程都属于自由(unconfined)进程;
role:定义文件、进程和用户的用途,如:文件:object_r,进程和用户:system_r;
type:指定主体和客体的类型,规则中定义何种进程域访问何种文件类型,targeted策略结果集基于type实现,如:admin_home_t,public_content_t(多服务共用);
sensitivity:限制访问的需要,由组织定义的分层安全级别,如:unclassified,confidential ,secret,top secret, 一个对象有且只有一个sensitivity,分0-15级,s0最低,targeted策略结果集默认使用s0;
category:对于特定组织划分不分层的分类,如:FBI Secret,NSA secret,一个对象可以有多个categroy,c0-c1023共1024个分类,targeted 策略结果集不使用category。
实际上下文:存放在文件系统中,但在CentOS5系列发行版本中,只是标识了前三个元素,在后续的CentOS6和CentOS7系列发行版本中也只是标识了前四个元素。而标识归标识,真正起作用的也只有第三个字段,该字段对于文件来说称为“类型”,对于进程来说称为“域”。可以使用ls -Z命令来查看文件的安全上下文;可以使用ps -Z命令来查看进程的安全上下文:
在CentOS5.11中的查看/root目录的结果:
[root@CentOS511A ~]# ls -Z -rw------- root root system_u:object_r:user_home_t anaconda-ks.cfg -rw-r--r-- root root root:object_r:user_home_t install.log -rw-r--r-- root root root:object_r:user_home_t install.log.syslog
在CentOS6.8中的查看/root目录的结果:
[root@Centos68A ~]# ls -Z -rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg -rw-r--r--. root root system_u:object_r:admin_home_t:s0 install.log -rw-r--r--. root root system_u:object_r:admin_home_t:s0 install.log.syslog
在CentOS7.2中的查看/root目录的结果:
[root@Centos72A ~]# ls -Z -rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg
我们可以发现,即便是CentOS5、6、7三个系列的发行版本中SELinux全都默认使用了targeted策略结果集,但是他们所应用的策略结果集其实是不同的。
[root@CentOS511A ~]# ls /etc/selinux/targeted/policy/ policy.21
[root@Centos68A ~]# ls /etc/selinux/targeted/policy/ policy.24
[root@Centos72A ~]# ls /etc/selinux/targeted/policy/ policy.29
期望(默认)上下文:存放在二进制的SELinux策略结果集(映射目录和期望安全上下文)中。
下面是在CentOS5.11、6.8、7.2上查看的默认上下文设置,只列举了根的一级子目录的相关内容,因内容太多,其余的均已省略。
[root@CentOS511A ~]# semanage fcontext -l SELinux fcontext type Context /.* all files system_u:object_r:default_t:s0 /xen(/.*)? all files system_u:object_r:xen_image_t:s0 /nsr(/.*)? all files system_u:object_r:var_t:s0 /mnt(/[^/]*) symbolic link system_u:object_r:mnt_t:s0 /mnt(/[^/]*)? directory system_u:object_r:mnt_t:s0 /lib(64)?/dbus-1/dbus-daemon-launch-helper regular file system_u:object_r:bin_t:s0 /lib/.* all files system_u:object_r:lib_t:s0 /bin/.* all files system_u:object_r:bin_t:s0 /usr/.* all files system_u:object_r:usr_t:s0 /var/.* all files system_u:object_r:var_t:s0 /dev/.* all files system_u:object_r:device_t:s0 /etc/.* all files system_u:object_r:etc_t:s0 /opt/.* all files system_u:object_r:usr_t:s0 /srv/.* all files system_u:object_r:var_t:s0 /tmp/.* all files <<None>> /sys/.* all files <<None>> (……后续内容省略)
[root@Centos68A ~]# semanage fcontext -l SELinux fcontext type Context /.* all files system_u:object_r:default_t:s0 /[^/]+ regular file system_u:object_r:etc_runtime_t:s0 /a?quota\.(user|group) regular file system_u:object_r:quota_db_t:s0 /nsr(/.*)? all files system_u:object_r:var_t:s0 /sys(/.*)? all files system_u:object_r:sysfs_t:s0 /xen(/.*)? all files system_u:object_r:xen_image_t:s0 /mnt(/[^/]*) symbolic link system_u:object_r:mnt_t:s0 /mnt(/[^/]*)? directory system_u:object_r:mnt_t:s0 /bin/.* all files system_u:object_r:bin_t:s0 /dev/.* all files system_u:object_r:device_t:s0 /lib/.* all files system_u:object_r:lib_t:s0 /srv/.* all files system_u:object_r:var_t:s0 /var/.* all files system_u:object_r:var_t:s0 /tmp/.* all files <<None>> /usr/.* all files system_u:object_r:usr_t:s0 /opt/.* all files system_u:object_r:usr_t:s0 /etc/.* all files system_u:object_r:etc_t:s0 /root(/.*)? all files system_u:object_r:admin_home_t:s0 (……后续内容省略)
[root@Centos72A ~]# semanage fcontext -l SELinux fcontext type Context /.* all files system_u:object_r:default_t:s0 /[^/]+ regular file system_u:object_r:etc_runtime_t:s0 /a?quota\.(user|group) regular file system_u:object_r:quota_db_t:s0 /nsr(/.*)? all files system_u:object_r:var_t:s0 /sys(/.*)? all files system_u:object_r:sysfs_t:s0 /xen(/.*)? all files system_u:object_r:xen_image_t:s0 /mnt(/[^/]*)? symbolic link system_u:object_r:mnt_t:s0 /mnt(/[^/]*)? directory system_u:object_r:mnt_t:s0 /bin/.* all files system_u:object_r:bin_t:s0 /dev/.* all files system_u:object_r:device_t:s0 /opt/.* all files system_u:object_r:usr_t:s0 /var/.* all files system_u:object_r:var_t:s0 /srv/.* all files system_u:object_r:var_t:s0 /usr/.* all files system_u:object_r:usr_t:s0 /tmp/.* all files <<None>> /run/.* all files system_u:object_r:var_run_t:s0 /etc/.* all files system_u:object_r:etc_t:s0 /lib/.* all files system_u:object_r:lib_t:s0 /root(/.*)? all files system_u:object_r:admin_home_t:s0 (……后续内容省略)
经过上述在三个不同发行版本的CentOS系统中SELinux默认上下文的对比,我们发现:在CentOS5中,上下文的定义比较少而且不够精细,而CentOS6和CentOS7相比较来说差别不大,而且类型更多,上下文的定义更明确了。
SELinux的策略结果集及策略结果集应用规则:
主体(subject):进程称为主体
客体(object):所有可以读取的对象,包括文件、目录和进程,端口等。
安全策略:定义主体读取对象的规则数据库,规则中记录了哪个类型的主体使用哪个方法读取哪一个客体是允许还是拒绝的,并且定义了哪种行为是允许的或是拒绝的。
在Linux(如CentOS系列发行版Linux)系统中SELinux赋予所有的文件一个type的文件类型标签,赋予所有的进程一个domain的标签。domain标签能够执行的操作在安全策略中定义。当一个主体试图访问一个客体时,内核中的策略执行服务器将检查AVC (Access Vector Cache,访问矢量缓存)。在AVC中,主体和客体的权限被缓存(cached),查找“应用+文件”的安全环境。然后根据查询结果进行允许访问或拒绝访问的判断。
与SELinux相关命令,命令的执行结果略去,有兴趣的小伙伴可以自己敲敲试试看:
获取selinux当前状态:
[root@Centos68A ~]# getenforce
查看selinux状态:
[root@Centos68A ~]# sestatus:
设置SELinux的模式(强制模式和警告模式)
[root@Centos68A ~]# setenforce {0|1}
0:设置为permissive
1:设置为enforcing
给文件重新打安全标签:
[root@Centos68A ~]# chcon [OPTION]... [-R] [-u USER] [-r ROLE] [-t TYPE] FILE... [root@Centos68A ~]# chcon [OPTION]... [-R] --reference=RFILE FILE...
恢复目录或文件默认的安全上下文:
[root@Centos68A ~]# restorecon [-R] /path/to/somewhere
查看默认的安全上下文:
[root@Centos68A ~]# semanage fcontext -l
添加默认安全上下文到策略结果集:
[root@Centos68A ~]# semanage fcontext -a -t httpd_sys_content_t ‘/testdir(/.*)?‘ [root@Centos68A ~]# restorecon -Rv /testdir
从策略结果集中删除默认安全上下文:
[root@Centos68A ~]# semanage fcontext -d -t httpd_sys_content_t ‘/testdir(/.*)?‘
查看端口标签:
[root@Centos68A ~]# semanage port -l
添加端口:
[root@Centos68A ~]# semanage port -a -t http_port_t -p tcp 8090
删除端口:
[root@Centos68A ~]# semanage port -d -t http_port_t -p tcp 8090
修改端口:
[root@Centos68A ~]# semanage port -m -t http_port_t -p tcp 8090
查看布尔型规则命令:
[root@Centos68A ~]# getsebool [-a] [boolean] [root@Centos68A ~]# semanage boolean -l
查看修改过的布尔值:
[root@Centos68A ~]# semanage boolean -l -C
设置布尔型规则的布尔值的命令:
[root@Centos68A ~]# setsebool [-P] boolean value(On或Off) [root@Centos68A ~]# setsebool [-P] boolean=value(0或1)
为了将SELinux违规操作的错误的信息写入/var/log/message,要安装下面的包:
[root@Centos68A ~]# yum install setroublesshoot*
安装完成以后,需要重新启动才能开启setroublessshoot的功能。人为的制造几次SELinux违规操作,之后可以使用下面的命令来查看结果:
[root@Centos68A ~]# grep "setroubleshoot"/var/log/messages
根据日志中的内容执行下列命令即可:
[root@Centos68A ~]# sealert -l “UUID”
(待续……)
本文出自 “运维者的家” 博客,请务必保留此出处http://zhaotianyu.blog.51cto.com/132212/1817939
原文地址:http://zhaotianyu.blog.51cto.com/132212/1817939