Linux中的selinux


selinux是美国国家安全局发起的一个项目,它的目的是将系统加固到可以达到军方的级别。这也为Linux的安全提供了更强有力的保障。

所谓DAC,是自主访问控制,就是每一个用户为了能够实现和其他用户共享文件,在使用ACL之前,只能通过改变这个文件其他用户的权限,但是这种方法给系统安全带来了很多隐患。所谓CS,就是安全上下文,它取决于发起用户的权限和文本本身的权限。

所谓MAC,就是Mandatory Access Control,也就是强制访问控制,它是selinux实现访问控制的基础,selinux通过type enforce(TE)也就是强制类型来实现。

标准的Unix安全模型是任意的访问控制,也就是DAC,任何程序对其资源享有完全的控制权。假设某个程序打算把含有潜在重要信息的文件扔到/tmp目录下,那么在DAC的情况下没有人能够阻止它。但是selinux中的MAC也允许程序在/tmp目录下建立文件,也允许这个文件按照Unix权限字的要求对全世界刻度,但是当Unix许可检查应用后,selinux许可检查还要进一步判断对资源的访问是否被许可。selinux可以限制每一个进程对各种资源的访问和访问的权级。就是谁当一个进程在使用含有敏感数据时,这些数据会被禁止写入那些低权级进程可读的文件中。因此selinux提供了比传统的Unix权限更好的访问控制。

selinux是一种基于"域-类型"的模型的强制访问控制的安全系统,它被Linux2.6编写到内核中,相应的某些安全相关的应用也被打了selinux的补丁,最后还有一个相应的安全策略。

比如管理员可以允许一个应用程序添加记录到某一个日志文件但是不允许其重写或者删除该日志文件的内容,虽然ext3支持append-only标签,我们可以通过chattr来进行设置,但是该属性是不区分某一个进程的,不能再为一个访问append-only的同时,又允许另一个进程有完全的可写的权利,在另一方面,一个应用程序可以被允许在一个目录卡中建立文件并向其写入数据,但是不能删除文件。这些特性都是在没有selinux的普通的Linux内核所不能做到的,还有的就是,网络应用程序可以绑定到其需要的端口上,但是不能绑定到其他端口上。

我们的selinux通过operation的主语和宾语打一个"标签",在一个"类型"里只能由特定的目录或者用户执行。这里的operation通常是:读、写、执行等等。其实就是一个主谓宾的结构,也就是subject operation object的结构。而且它还有一个最小权限法则,比如定义httpd的目录/var/www为public_content_t类型,那么httpd就只能访问这个特定类型的文件或者目录,这些文件就叫做"沙箱",使用selinux时,必须精心设计一套访问法则。比如我们可以给不同的进程打上不同的"域",给不同的目录打上不同的"类型",然后通过定义"类型"和"域"的对应规则来实现。

selinux的实现机制有两种,一种是strict,此时任何进程都受selinux的控制,一般不适用,因为它的设定比较困难。一种是targeted,它由红帽开发,指定选定的进程来受selinux控制,这种机制使得selinux更加容易受到控制。

selinux的规则文件是以二进制文件存在的,他是编辑完成之后转换成为二进制文件,这样可以降低系统资源占用,该文件就是/etc/selinux/policy。而selinux可以吧一些规则里面可以方便控制的功能都设定为on或者off,这些都成为布尔类型,其中getsebool -a 可以显示这些布尔类型的内容。

在使用了selinux的系统中,每一个进程的上下文都包含了三个组成部分:一个ID,也就是identify,一个角色,也就是role,一个域,也就是domain。其中的ID是指这个进程的所有者,就是Unix账户,但是前提账是这个账户必须被预先编译到selinux策略中,这样selinux才能够认识这个账户,不然的话selinux默认地将那些未知的系统进程ID标记为system_u,将那些未知的用户进程ID标记为user_u,通常角色用来判断某个处于此角色的ID可以进入哪些域,还可以用来防止某个处于此角色的ID进入其他不该进入的域。

其实域也是和一个进程相对应的一个类型,所以当检查某个进程是否有权向另一个进程发送信号的时候,接受信号的进程的域就会充当"域-类型"模型中的"类型"的角色,从而完成"域-类型"的规则检查。也就是完成了进程间通信权限的检查。由于对文件还没有使用角色这个机制,所以目前每个文件都被规定为object_r角色,这个角色只是一个位置,对策略没有任何影响。

文件的ID就是文件创建者的ID,策略源文件中使用这个方式来判断一个访问是否有权改变这个文件的上下文描述符。除非被访问的文件的描述符中的ID字段和访问该文件的进程的所有者的ID字段相同,无论是改变前还是改变后,否则进程无权改变一个文件的上下文描述符。

我们可以使用ls -Z来显示文件的标签,我们可以使用ps -Z来显示进程的标签,比如我们可以使用ps auxZ | grep httpd来查看selinux的具体信息。

我们可以使用chcon命令来修改上下文,而chcon是change context的缩写,chcon -t是修改为特定类型,其中-R是递归修改,可以改变目录下的所有目录,而--reference=以某个文件的标签为参照改成一样的标签,比如我们可以使用chcon -R --reference=/var/www/html /www,当然我们还可以直接修改,范例命令是chcon -t default_t /www/index.html。

我们可以使用restorecon来恢复默认安全上下文的修改,该命令的-R参数表示递归,该命令的-F参数表示强制,该命令的-v参数表示显示详细信息,我们可以使用restorecon -R -v -F /www来显示/www目录的详细CS信息。我们也可以使用semange来进行信息的修改,通常它的-d参数表示删除,-m表示修改,-a表示附加,-t表示类型。

我们可以使用getsebool -a | grep httpd来查看某个对应的布尔类型的值,我们可以进行设置setsebool httpd_enable_cgi=on,其中加上-p选项表示永久有效。

而有些文件是没有指定上下文的,也就是那些不支持rwx标签的文件系统,比如/sys、/dev、/selinux,ls命令就不会显示其上下文,对于不能使用stat命令查看当前状态的那些文件系统,ls命令会返回?--------,其中所有者和所有组也会被标记为?。而我们的id命令会返回当前shell的上下文。

当我们启动一个selinux时,init所做的第一件事就是挂载/proc文件系统,并且判断selinux是否被激活i,init通过selinuxfs文件系统来判断内核中是否有selinux,如果内核中没有selinux参数或者内核参数中selinux=0这一项,那么系统就会以一种叫做non-SE的状态继续引导启动。如果发现了selinux,那么/selinux虚拟文件系统将会被创建,然后init通过/selinux/policyvers来检查内核所支持的selinux版本。最后,相应的的策略数据/etc/selinux/X/policy/policy.YY就会被装载到内核当中了,这里的X是对应的策略,我们可以使用strict或者targeted。

相关内容