SELinux 直观操作指南
中英文对照版
*all cartoons by Máirín Duffy
难以置信,到2013年,SELinux已经诞生10年了。起初是Fedora Core 3 引进了SELinux,随后又被Red Hat Enterprise Linux 4引进。值得写篇文章给想要了解SELinux的初学者来庆祝一下...
SElinux是一个标签系统。系统中的每个进程、每个文件/目录对象,甚至每个网络端口、设备以及每个可能的主机名都会被打上一个标签。我们用编写标签相关的规则来控制带标签进程访问带标签的资源,比如一个文件。这个规则被称为“策略”。这些规则由kernel来强制执行。一般这种强制执行被称为MAC,即“强制访问控制”。
在SELinux中,用户甚至不能对其所拥有的对象自由访问。标准的Linux访问控制模型是基于用户/用户组 + 权限标记如rwx,一般被称为DAC,即“自主访问控制”。SELinux并没有标准Linux访问控制中的UID概念,或文件所属的用户/用户组概念,从而也没有了拥有一切权利的root进程的概念,而是所有操作都由标签控制。
Note: SELinux并不是要摒弃DAC控制模型。它是一种和DAC控制模型并存的强制执行模型。一个应用要进行操作,必须同时在DAC和MAC模型下取得权限。这种情况下进程操作遇到Permission Denied,可能会给管理员带来困惑,不过SELinux标签导致的问题,并不会出现Permission Denied情况,只有DAC模型下会遇到Permission Denied。
基于类型的强制执行
下面来更详细的了解下标签。SELinux中最主要的强制执行模型是基于类型的强制执行模型。简单来说,给进程定义标签要基于这个进程的类型,给文件对象定义标签也要基于其类型。
类比
想象一个这样的系统,系统中有猫和狗两种对象或称为活物,那么“cat”和“dog”就是这两种活物的类型(type),在Linux中,就是进程的类型。
在这个系统中,还有另一种类别(class)的对象,这种对象是非活物,也就是被活物操作或者活物可以与之交互的东西,我们把它定义为“food”,这里的“food”并不是一个对象,而是对象的一个类别(class)。我们还想把这种类别的对象分成两个种类(types):“cat_chow”和“dog_chow”(译注:原文可能有笔误)。
作为策略制定者,我会让一个dog对象(一条狗)有吃种类为“dog_chow” 、类型为“food”的对象(狗粮)的权限,让一个cat对象(一只猫)有吃种类为“cat_chow”、类型为“food”的对象(猫粮)的权限。在SELinux中,这个规则要这样写进“策略”中:
allow cat cat_chow:food eat;
allow dog dog_chow:food eat;
有了上面的规则,kernel才会允许标签为“cat”的进程对带有“cat_chow”标签的“food”类型的对象执行“eat”操作,标签为“dog”的进程对带有“dog_chow”标签的“food”类型的对象执行“eat”操作。
但是在SELinux系统中,所有操作默认都是不被允许的。这就意味着,“dog”进程想要去对“cat_chow”标签的“food”做“eat”操作,是会被kernel拒绝的。
类似的“cat”类型的进程也不能去对“dog_chow” “food”做“eat”操作。
实际情况
我们赋予Apache进程httpd_t标签,Apache进程相关内容赋予httpd_sys_content_t和httpd_sys_content_rw_t标签。假设我们的信用卡信息储存在一个赋予msyqld_data_t标签的mySQL数据库中。如果一个Apache进程被入侵,黑客就可以控制httpd_t类型的进程,从而拥有了读取httpd_sys_content_t文件以及写入httpd_sys_content_rw_t文件的权限。但是即使Apache进程是root进程,黑客也无法获得读取信用卡数据(mysqld_data_t)的权限。这种情况下SELinux将黑客入侵的危害降到了最低。
MCS强制执行(MCS:多类别安全)
类比
之前,dog进程和cat进程被标签分类,但是如果有多个dog进程,例如Fido 和 Spot,我们要告诉kernel阻止Fido吃Spot的dog_chow又该怎么做呢?
一种办法是定义更多新的类型,如定义新的进程类型Fido_dog,以及新的food种类 Fido_dog_chow。但是你很快会发现这样的方法可操作性太差,因为所有的dog类型都需要类似的权限。每个新的dog进程类型都定义一个新的food种类与之对应,是多么令人抓狂的事。
为了处理这种情况,SELinux中有一种新的强制控制模型,称为MCS (Multi Category Security)(多类别安全)。在MCS中,标签中增加了另外的字段,该字段可以同时赋予dog进程和dog_chow food对象。对于两个dog进程设置如下标签:dog:random1(Fido进程)和dog:random2(Spot进程)。
对于两个food对象设置如下标签:dog_chow:random1(Fido的food)和 dog_chow:random2(Spot的food)
在MCS规则下,进程要想有权限访问资源,必须首先符合类型强制控制的规则,其次随机的MCS标签要完全匹配,否则访问会被拒绝。
实际情况:
在计算机系统中,经常有很多进程拥有相同的访问权限的情况,但是我们又想要让其彼此有互相独立的访问权限。这种情况通常被称为多租户环境。最好的例子就是虚拟机系统。例如一台服务器上运行着很多虚拟机,如果其中一个虚拟机被入侵,我们肯定希望其他的虚拟机及其镜像不受这次入侵的影响。但是在基于类型的强制访问系统中,KVM虚拟机是被赋予svirt_t标签的,其镜像被赋予标签svirt_image_t。对应的规则是svirt_t 可以 read/write/delete 有标签svirt_image_t的内容,这样是无法满足前面描述的安全需求的。不过libvirt不仅实现了基于类型的强制访问模型,还实现了MCS机制。当libvirt启动一个虚拟机进程时,该机制会随机生成一个类似于 s0:c1,c2的MCS标签,然后给这台虚拟机将要管理的内容都赋予标签svirt_t:s0:c1,c2标签。最后,该虚拟机进程被赋予了标签:svirt_t:s0:c1,c2。这样,即使拥有root权限的虚拟机(标签为svirt_t:s0:c1,c2)被黑客控制,SELinux kernel也可以拒绝svirt_t:s0:c1,c2标签的进程访问标签为svirt_image_t:s0:c3,c4的内容。
OpenShift中使用了类似的策略,每个gear(user/app/process)(译注:gear可以认为类似于Linux中的进程概念)以同一个SELinux类型openshift_t运行。策略定义了规则来控制gear类型的访问,并且每个gear都有唯一的MCS标签来保证不同的gear间不会互相发生访问。
这个短视频展示了如果一个Openshift gear变成root权限会发生什么。
MLS 强制执行模型(多级别安全模型)
另一种SELinux强制执行模型用的比较少,称为MLS(Multi Level Security)强制执行模型;这种模型开发于60年代,主要用于可信操作系统例如Trusted Solaris。
主要思想是基于进程要访问数据的安全级别来进行控制。一个secret级别的进程不能读取top secret级别的数据。
MLS与MCS非常类似,区别主要是MLS中增加了对强制执行策略“支配”的概念。MCS中标签必须完全匹配才能授予权限,而MLS中一个高级别的标签可以支配低级别的标签并且能获得访问权限。
类比
现在用不同种类的dog做类比,注意不是不同名字的dog。比如一个品种是Greyhount,另一个品种是Chihuahua。
我们想要让Greyhound可以吃任何dog food,但是一只Chihuahua dog不能去吃Greyhound dog food,因为这样可能会导致Chihuahua窒息而死。
我们给Greyhound赋予标签dog:Greyhound,对应的dog food 赋予标签dog_chow:Greyhound,赋予Chihuahua dog:Chihuahua标签,对应的dog food 赋予dog_chow:Chihuahua标签。
在MLS策略下,我们让MLS Greyhound 标签支配Chihuahua 标签。这意味着dog:Greyhound 允许吃dog_chow:Greyhound 和 dog_chow:Chihuahua。(译注:可以认为Greyhound的级别比Chihuahua的级别高)
但是 dog:Chihuahua 却不能吃dog_chow:Greyhound。
当然,在基于类型的强制执行模型下,dog:Greyhound和dog:Chihuahua仍然不能去吃cat_chow:Siamese。
实际情况
我可能有两个Apache服务:进程A以标签httpd_t:TopSecret运行,进程B以httpd_t:Secret运行。如果进程B被入侵,黑客可以读取标签为httpd_sys_content_t:Secret的数据,但是却不能读取标签为httpd_sys_content_t:TopSecret的数据。
然而,如果进程A被入侵,那么黑客就能同时获取httpd_sys_content_t:Secret和httpd_sys_content_t:TopSecret两种标签下的数据。
一般情况MLS机制被用于军用环境中,在这种环境中往往有这样的需求:一个用户可能只允许访问秘密级别的数据,但另一个用户在同一个系统中可以访问绝密级别的数据。
总结
SELinux是一个强大的标签化系统,由kernel来控制每一个进程对其他资源的访问权限。其中最主要的功能是基于类型的强制执行模型,这种模型由很多策略规则来授予进程的访问权限,其权限是基于进程的标签和进程访问对象的标签。另外还有两种控制模型来隔离相同类型的进程之间的交互,完全互相隔离的模型叫MCS(多类别安全模型),允许有支配关系的模型称为MLS(多级别安全模型)。
原文链接