分类目录归档:SELinux 基础

fedroa 20 了解selinux的最新变化

查看当前规则库的主要信息:

查看policy定义的所有selinux用户

查看system_u 用户的角色及mls range

查看selinux的manager

查看按照pp的条目

查看seliunxfs伪文件系统标签。

查看selinux安全上下文对应的sid

SELinux:2. selinux概念

SELinux访问控制机制和策略语言的详细内容非常广泛,将在后面的章节中进行描述。但SELinux的基本概念和目标是相当简单的,在这一章 中,我们将学习SELinux的安全概念,并在这些概念后进行练习。要有效使用和应用SELinux访问控制,理解其概念是非常必要的,这一章主要集中介 绍SELinux的访问控制特性和类型强制(TE),同时我们也简要地介绍了一下非强制的多层安全机制。

1.类型强制的安全上下文


所有操作系统访问控制都是以关联的客体和主体的某种类型的访问控制属性为基础的。在SELinux中,访问控制属性叫做安全上下文。所有客体(文 件、进程间通讯通道、套接字、网络主机等)和主体(进程)都有与其关联的安全上下文,一个安全上下文由三部分组成:用户、角色和类型标识符。常常用下面的 格式指定或显示安全上下文:

这个字符串标识符中的每个元素使用SELinux策略语言进行定义,后面我们会对策略语言进行详细的描述,现在只需要理解一个有效的安全上下文必须 要有一个有效的用户、角色和类型标识符,通过策略编写器定义标识符,每一个标识符的命名空间正交的,因此,用户、角色和类型的标识符可能相同,但不合理, 也不建议这么定义。
安全上下文示例
SELinux对系统中的许多命令做了修改,通过添加一个-Z选项显示客体和主体的安全上下文,例如:ls -Z显示文件系统客体的安全上下文,ps -Z显示进程的安全上下文,另一个有用的命令是id,它显示了你的shell的安全上下文(即你当前的用户、角色和类型),下面的例子显示了一个运行 SELinux的shell安全上下文:

你可以使用本章中我们列出的这些命令研究你自己的SELinux系统。

2 对比SELinux和标准Linux

至此,比较标准Linux和SELinux之间的访问控制属性显得非常有用,为了使表述简化,我们只固定讨论文件系统客体如文件和目录。在标准 Linux中,主体的访问控制属性是与进程通过在内核中的进程结构关联的真实有效的用户和组ID,这些属性通过内核利用大量工具进行保护,包括登陆进程和 setuid程序,对于客体(如文件),文件的inode包括一套访问模式位、文件用户和组ID。以前的访问控制基于读/写/执行这三个控制位,文件所有 者、文件所有者所属组、其他人各一套。

在SELinux中,访问控制属性总是安全上下文三人组形式,所有客体和主体都有一个关联的安全上下文,标准Linux使用进程用户/组ID,文件 的访问模式,文件用户/组ID要么可以访问要么被拒绝,SELinux使用进程和客体的安全上下文,需要特别指出的是,因为SELinux的主要访问控制 特性是类型强制,安全上下文中的类型标识符决定了访问权。

注意:SELinux在标准Linux基础上增加了类型强制,这就意味着标准Linux和SELinux访问控制都必须满足先要能访问一个客体,例如:如果我们对某个文件有SELinux写入权限,但我们没有该文件的w许可,那么我们也不能写该文件。

表2-1.标准Linux和SELinux访问控制比较

3 安全上下文

安全上下文是一个简单的、一致的访问控制属性,在SELinux中,类型标识符安全上下文的主要组成部分,由于历史原因,一个进程的类型通常被称为 一个域(domain),”域”和”域类型”意思都是一个,我们不必苛刻地去区分或避免使用术语域,通常,我们认为域、域类型、主体类型和进程类型都是同 义的。

安全上下文中的用户和角色标识符除了对强制有一点约束之外对类型强制访问控制策略没什么影响,我们将在第7章”约束”中讨论,对于进程,用户和角色 标识符显得更有意义,因为它们用于控制类型和用户标识符的联合体,这样就会Linux用户账号关联起来;然而,对于客体,用户和角色标识符几乎很少使用, 为了规范管理,客体的角色常常是object_r,客体的用户常常是创建客体的进程的用户标识符,它们在访问控制上没什么作用。

最后,一定要清楚标准Linux安全中的用户ID和安全上下文中的用户标识符之间的区别,就技术而论,它们是正交标识符,分别用于标准的和安全增强 的访问控制机制,这两者之间的任一相互关联都是通过登陆进程按照规范严格规定的,而不是通过SELinux策略直接强制实施的。

4 类型强制访问控制

在SELinux中,所有访问都必须明确授权,SELinux默认不允许任何访问,不管Linux用户/组ID是什么。这就意味着在SELinux 中,没有默认的超级用户了,与标准Linux中的root不一样,通过指定主体类型(即域)和客体类型使用allow规则授予访问权限,allow规则由 四部分组成:

源类型(Source type(s) ) 通常是尝试访问的进程的域类型
目标类型(Target type(s) ) 被进程访问的客体的类型
客体类别(Object class(es)) 指定允许访问的客体的类型
许可(Permission(s)) 象征目标类型允许源类型访问客体类型的访问种类
举一个例子进行说明,如:

这个例子显示了TE allow规则的基础语法,这个规则包含了两个类型标识符:源类型(或主体类型或域)user_t,目标类型(或客体类型)bin_t。标识符file是 定义在策略中的客体类别名称(在这里,表示一个普通的文件),大括号中包括的许可是文件客体类别有效许可的一个子集,这个规则解释如下:

拥有域类型user_t的进程可以读/执行或获取具有bin_t类型的文件客体的属性。
正如我稍后会讨论的,SELinux中的许可相对标准Linux而言要更细一些,在标准Linux中只有三种(rwx)。在这里,read和 execute是十分常见的,getattr明显要少得多,实质上,文件的getattr许可只不过允许调用者查看(不修改)如日期、时间等属性,以及任 意访问控制(DAC)访问模式。在一个标准Linux系统中,调用者只有搜索文件所在目录的权限,但也可能看到关于文件的信息,因为他可以通过搜索目录来 看到文件的某些信息,即使他没有该文件的访问权限。

假设user_t是一个普通的、无特权的用户进程如一个登陆shell进程域类型,bin_t是与用户运行的执行文件(如/bin/bash)关联的类型,策略中的规则可能允许用户执行shell程序如bash shell。

注意:在类型标识符名字中的_t没有意义,只不过是在大多数SELinux策略中惯用的约定,策略编写器可以通过策略语言语法允许的任何合适的规范定义类型标识符。

在这一章中,我们使用符号圆圈代表进程,方框代表客体,箭头代表允许的访问来描绘允许的访问,例如:如2-1描绘了前面的allow规则允许的访问。

5 .类型强制示例

SELinux allow规则如之前的例子在SELinux中实际上都是授予访问权的,真正的挑战是如何保证数以万计的访问正确授权,只授予必须的权限,实现尽可能的安全。

为了进一步研究类型强制,我们以管理密码的程序(即passwd)为例进行说明,在Linux中,passwd程序是可信任的,修改存储经过加密的 密码的影子密码文件(/etc/shadow),passwd程序执行它自己内部的安全策略,允许普通用户修改属于他们自己的密码,同时允许root修改 所有密码。为了执行这个受信任的作业,passwd程序需要有移动和重新创建shadow文件的能力,在标准Linux中,它有这个特权,因为 passwd程序可执行文件在执行时被加上了setuid位,它作为root用户(它能访问所有文件)允许,然而,许多程序都可以作为root允许(实际 上,所有程序都有可能作为root允许)。这就意味着任何程序(当以root身份运行时)都有可能能够修改shadow文件。类型强制使我们能做的事情是 确保只有passwd程序(或类似的受信任的程序)可以访问shadow文件,不管运行程序的用户是谁。

下图描绘了在SELinux系统中passwd程序如何使用类型强制进行工作的

在这个例子中,我们定义了两个类型,passwd_t类型代表密码程序使用的域类型,shadow_t类型代表shadow密码文件的类型。如果我们在磁盘上检查这个文件,我们将会看到:

同样,在这个策略下检查运行密码和程序的进程将会看到:

现在,你可以忽略安全上下文的用户和角色元素,只需注意类型就行了。

检查图2-2中的allow规则,这个规则的目的是授予passwd进程的域类型(passwd_t)访问shadow的文件类型 (shadow_t),需要允许进程移动并创建一个新的shadow密码文件。重新回到图2-2中,我们看到描绘运行密码程序(passwd)的进程能够 成功管理shadow密码文件,因为它有一个有效的root用户ID(标准Linux访问控制),同时因为TE allow规则允许它访问shadow密码文件的类型(SELinux访问控制),两者都是必须的,但都不充分。

6 域转变的问题

如果我们所做的所有事情是为进程提供对客体如文件的许可访问,编写一个TE策略应该是直截了当的事情。然而,我们不得不找出用正确的域类型安全正确 地运行一个程序的方法。例如:我们不想程序由于某种原因在一个进程中用passwd_t域类型不受信任地访问shadow文件,这可能是灾难性的,这个问 题带来了域转变的问题。

为了说清楚这个问题,下图中,我们扩展了前面的密码程序示例,在一个普通的系统中,用户(如Joe)登陆进系统,通过登陆进程会创建一个 shell进程(如运行bash)。在标准Linux安全中,真实有效的用户ID(即Joe)是相同的[1],在我们的SELinux策略示例中,我们看 到进程类型是user_t,它表示一个普通的、不受信任的用户进程域类型。当Joe的shell程序运行其他程序时,新进程的类型将会保留user_t域 类型,除非做了其他操作,那么Joe如何修改密码呢?
[1]正确地说,Joe不是用户ID,Joe只不过是在密码文件(/etc/passwd)中表示用户的字符串而已,为了使解释更浅显易懂,我跳过了中间的步骤,在我们的例子中只使用字符串标识符。

域转变的问题

我们不应该让Joe的不受信任的域类型user_t能够直接读写shadow密码文件,因为这样将会允许任何程序(包括Joe的shell)看到并 修改这个关键文件的内容。正如前面讨论的,我们只想密码程序有这个访问权,然后只以passwd_t域类型运行它。那么,问题是如何提供一个安全可靠的并 且比较隐蔽的方法将Joe的以user_t类型运行的shell转变为一个以passwd_t类型运行密码程序的进程。

7标准Linux安全中的setuid程序

在我们讨论如何处理域转变的问题之前,首先看一下类似的问题在标准Linux中是如何处理的,即Joe想安全地修改现有的密码问题,Linux解决 这个问题的方法是通过给passwd赋一个setuid值,使其执行时具有root权限,如果你在一个普通Linux系统上列出密码文件,你看到的会是:

 

这 里注意两件事,第一个是在所有者权限的x位置被设置为s了,这就是所谓的setuid位,意思是任何执行这个文件的进程,它的有效UID(即用户ID)将 会被改为文件所有者。这里,root是文件所有者,因此当执行密码程序时实际上将会以root用户的ID运行,图2-4显示了这些步骤。

标准Linux中密码程序安全(setuid)

图.标准Linux中密码程序安全(setuid)
当Joe运行密码程序时真正会发生的是他的shell将会产生一个fork()系统调用创建一个它自身的副本,这个复制进程仍然有真实有效的用户 ID(joe),并且仍然运行有shell程序(bash)。然而,在调用完fork指令后,新的进程将会产生一个execve()系统调用来执行密码程 序。标准Linux安全需要调用的用户ID(仍然是joe)有x权限,这里确实就是这样,因为所有人都有x权限。成功执行execve()调用将会发生两 件非常关键的事情,第一件是运行在新进程中的shell程序将会被passwd程序替换,第二,因为setuid位是为所有者设的,真正的用户ID将从进 程的原始ID改为文件所有者的ID(这里是root),因为root可以访问所有文件,那么密码程序也就可以访问shadow密码文件了,也就可以处理 Joe修改密码的需求了。

setuid位的使用在类Unix操作系统中非常普遍,这是它们的一个简单但强大的特性,然而,它也成为标准Linux安全的主要弱点,密码程序需 要以root身份运行访问shadow文件,然而,当以root身份运行时,密码程序可以访问所有的系统资源,这就违背了中心安全工程的最小权限原则,结 果,我们必须信任密码程序,对于信任的安全应用程序,密码程序需要一个扩展的代码审核来确保它不会滥用它的特权,而且,当遇到无法预见的错误时,会影响到 密码程序,这样就可能会将缺陷引入,即使密码程序相当简单且是高度受信任的,想象一下其他程序(包括登陆shell)可能以root身份运行将会是多么可 怕的。

我们真正要做的事情应该是确保为密码程序设置最小权限,我们认为密码程序应该只能访问shadow文件和其他与密码有关的文件,再加上那些必须的最 小系统资源,同时我们还应该确保除了密码程序能访问shadow文件外,其他程序都不能访问这个文件,这样说来,我们就只需要关心密码程序它自身的角色就 行了,不用管用户账号了。
这就是马上会描述的类型强制。

8.域转变

在前面的图中,allow规则确保passwd进程域类型(passwd_t)可以访问shadow密码文件,然而,我们仍然有前面已经提到 的域转变问题,提供一个安全的域转变与setuid程序的原理非常类似,但强化了类型强制,为了解释清楚一点,下面我们以在setuid的例子中增加类型 强制为例进行说明(如下图)。

 

SELinux中的密码程序安全(域转变)

图.SELinux中的密码程序安全(域转变)
现在,我们的例子变得更复杂了,让我们一起来详细看看这张图。首先,注意我们在前面的基础上增加了三个类型,即Joe的shell域 (user_t),密码程序的域类型(passwd_t)和shadow密码文件的类型(shadow_t)。此外,我们为passwd可执行文件增加了 文件类型(passwd_exec_t)。例如:列出密码程序的安全上下文时,将会看到:

 

现在我们有足够的信息来创建TE策略规则允许密码程序(大概只有密码程序)以passwd_t域类型运行,让我们来看一看图2-5中的规则,第一条规则是:

这条规则所做的事情是允许Joe的shell(user_t)在passwd可执行文件 (passwd_exec_t)上启动execve()系统调用,SELinux execute文件权限实际上与标准Linux中的x访问权限是一样的,尝试执行之前shell先”统计”文件,因此需要getattr权限,回想一下我 们在前面描述的shell程序实际上是如何工作的,首先它派生出自身的一个副本,包括相同的安全属性,这个副本仍然保留了Joe的shell原始域类型 (user_t),因此,必须给原始域(即shell的域类型)赋予执行权限,那就是为什么user_t是这个规则的源类型的原因了。
下面让我们来看看图2-5中的第二个规则:

这条规则提供了对passwd_t域的入口访问权,entrypoint许可在SELinux中是一个相当有用的许可权限,这个权限所做的事情是定 义哪个可执行文件(程序)可以”进入”某个特定的域,对于域转变,新的或将要进入的域(这里是passwd_t)必须具有访问可执行文件的 entrypoint许可权,以转变到新的域类型,在这个例子中,假设只有passwd可执行文件被标识为passwd_exec_t,并且只有 passwd_t类型有entrypoint权限访问passwd_exec_t,这样我们就具备了只有密码程序才能运行在passwd_t域类型中的条 件,这是一个强大的安全控制。

警告:entrypoint许可权限的概念是相当重要的,如果你没有完全理解前面的示例,在开始行动前,请重新阅读一次。
让我们在看一看最后的规则:

这是我们第一次看到的allow规则没有提供对文件客体的访问,在这个例子中,客体类别是process,意味着客体类别代表进程,回想一下前面的 内容,所有的系统资源都被封装为客体类别,这个概念也包括进程,在这最后一个规则中,许可是TRansition 访问,在允许修改进程的安全上下文的类型时,需要这个许可,原始的类型(user_t)到新的类型(passwd_t)进行域转变必须有 TRansition 许可才允许进行。

这三条规则一起提供了域转变发生时必须的访问权,对于一个成功的域转变,这三条规则都是必须的,任何单独一个都是不够充分的,因此,域转变只有在同时满足下面的三个条件时才允许进行:

1、进程的新域类型对可执行文件类型有enTRypoint 访问权
2、进程的当前(或旧的)域类型对入口文件类型有execute 访问权
3、进程当前的域类型对新的域类型有transition 访问权

当这三个许可在一个TE策略中都被通过后,才可能发生域转变,而且,在可执行文件上使用entrypoint 许可,我们有能力严格控制哪个程序可以用给定的域类型运行,execve()系统调用是修改域类型的唯一方法[2],使得策略编写器可以很好地控制任何一 个程序的访问特权,而不管调用程序的用户。

[2]更精确地说,为SELinux最近对进程的修改提供了一个方法,赋予必须的特权,修改它的安全上下文,而不使用execve()调用,通常,这个机制将会在第5章”类型强制”中描述,它没有一个强健的理由,我们不应该使用它,因为它大大地削弱了类型强制的强健性。

现在的问题是Joe如何指出他想要的域转变,上面的规则只允许域转变,他们不需要它,程序员或用户 有多种方法明确请求一个域转变(如果允许),但通常情况下,我们不想让用户明确地发出这些请求,Joe想做的是允许密码程序,它希望系统确保他能完成这个 任务,我们需要一个方法让系统默认启动域转变。

9.默认域转变:type_transition指令

为了支持默认的域转变,我们需要引入一个新的规则,类型转变规则(type_transition),这个规则为SELinux策略提供一个方法指 定默认应该尝试的转变,在没有明确指出需要的转变时,让我们在allow规则后面添加一个type_transition规则:

这个规则的语法与allow规则有点不一样了,但仍然有源和目标类型(分别是user_t和passwd_exec_t),也有客体类别(process),然而,许可相反了,我们有了第三个类型,默认类型(passwd_t)。
type_transition规则用于多中不同的与修改默认类型相关的目的,现在,我们关心将process作为它的客体类别的 type_transition规则,这个规则引发默认的域转变尝试,type_transition规则默认代表一个execve()系统调用,如果调 用的进程域类型是user_t,并且可执行文件的类型是passwd_exec_t(如图2-5中的示例),将会尝试到一个新域类型(passwd_t) 的域转变。
type_transition规则允许策略编写器引发默认的域转变,而不需要明确的用户输入,这使得类型强制减少了用户的强制闯入,在我们的例子 中,Joe不想知道任何关于访问控制或类型的事情,他只想修改它的密码,系统和策略设计人员可以使用type_transition规则使这些转变对于用 户而言是透明的。
注意:记住type_transition规则引发一个默认的域转变,但它不允许它执行,你还是必须为域转变成功发生提供三个需要的访问类型,无论是默认启动还是通过用户的明确请求启动。

10 角色

SELinux也提供了一种基于角色的访问控制(RBAC),SELinux的RBAC特性是依靠类型强制建立的,SELinux中的访问控制主要 是通过类型实现的,角色基于进程安全上下文中的角色标识符限制进程可以转变的类型,如此,策略编写器可以创建一个角色,允许它转变为一套域类型(假设类型 强制规则允许转变),从而定义角色的限制,以我们在图2-5中所举的密码程序为例,按照类型强制规则,密码程序可以通过user_t域类型执行,然后转到 新的passwd_t域,Joe的角色必须允许与新的域类型建立关联以便进行域转变,为了同图进行说明,我们在图2-6中扩展了密码程序示例。

域转变中的角色

图.域转变中的角色
在进程描述安全上下文内容中我们增加了角色部分(user_r),同时还增加了一个新的角色,在role语句中明确地指出:

 

role语句声明角色标识符以及与声明的角色有关的类型,前面的语句声明角色user_r(如果它在策略中还没有声明)以及与这个角色关联的类型 passwd_t,这个关联意味着passwd_t类型在安全上下文中允许与角色user_r共存,如果没有这个role语句,就不能创建新的上下文 joe:user_r:passwd_t,execve()系统调用也会失败,即使TE策略允许Joe的类型(user_t)有所有的访问权。

策略编写器可以定义更多约束的角色,然后将这些角色与用户关联起来,例如:设想一下,在我们的策略中,创建了一个角色叫做 restricted_user_r,除了它与passwd_t类型没有关联之外,与user_r一样,因此,如果Joe的角色是 restricted_user_r而不是user_r,Joe就不能通过认证运行密码程序,即使TE规则允许它的域类型访问。

 

11 SELinux中的多层安全

类型强制无疑是SELinux引入的最重要的强制访问控制(MAC)机制,然而,在某些情况下,主要是保密控制应用程序的一个子集,传统的多层安全 (MLS)MAC与类型强制一起使用显得更有价值,在这些情况下,SELinux总是包括某种格式的MLS功能,MLS特性是可选的,在SELinux的 两个MAC机制中,它通常不是最重要的那个,对大多数安全应用程序而言,包括许多非保密数据应用程序,类型强制是最适合的安全增强的机制,尽管如 此,MLS对部分应用程序还是增强了安全性。

MLS的基本概念在第1章”背景”中已经介绍过了,真实实施MLS更佳复杂,MLS系统使用的安全级别是层次敏感的,是一个(包括空集)非层次范畴 的集合。这些敏感度和范畴用于映射真实的机密信息或用户许可,在大多数SELinux策略中,敏感度(s0,s1,…)和范畴(c0,c1,…)使用 通配名,将它留给用户空间程序和程序库,以指定有意义的用户名。(例如:s0可能与UNCLASSIFIED 关联,s1可能与SECRET关联)

为了支持MLS,安全上下文被扩展了,包括了安全级别,如:

注意MLS安全上下文至少必须有一个安全级别(它由单个敏感度和0个或多个范畴组成),但可以包括两个安全级别,这两个安全级别分别被叫做 低(或进程趋势)和高(或进程间隙),如果高安全级别丢失,它会被认为与低安全级别的值是相同的(最常见的情况),实际上,对于客体和进程而言,低和高安 全级别通常都是相同的,通常用于进程的级别范围被认为是受信任的主体(即进程信任降级信息)或多层客体,如一个目录,它又包括了不同安全级别的客体。为了 使描述简单,假设所有的进程和客体都只有一个安全级别。

访问客体的MLS规则与第1章中描述的非常相似,除了安全级别是无层次的之外,但又提供了一个控制关系进行管理,不像等式那样,级别要么比另一个要 高,或相等,要么就比它低,在控制关系中,有一个叫做无可比的第四种状态(也叫做非可比的,查看下面列表中的incomp),安全级别通过控制关系而不是 范畴关联,它没有层次关系,有四个控制操作符可以将两个MLS安全级别关联起来,如:
dom:如果SL1的敏感度大于或等于SL2的敏感度,则SL1 dom(优于) SL2,SL1的范畴就是SL2范畴的一个超集。
domby:如果SL1的敏感度小于或等于SL2的敏感度,则SL1 domby SL2,SL1的范畴是SL2的子集。
eq:如果SL1的敏感度等于SL2的敏感度,则SL1 eq SL2,SL1和SL2的范畴也是相同的。
incomp:如果SL1的范畴和SL2的范畴不能进行对比(即既不是子集也不是超集或其他),那么SL1 incomp(不可对比)SL2。

提供了域关系,在SELinux中实现了多种Bell-La Padula模型,如果进程当前的安全级别优于客体的安全级别,进程则可以”读取”客体。如果低于客体的安全级别,则可以”写入”客体,因此,同时读写客体只要这两个安全级别相等就可以了。
SELinux中MLS的约束是附加在TE规则中的,如果启用了MLS,要授予访问权两个检查都必须通过,第8章”多层安全”将会讨论SELinux可选的MLS特性。

12 .精通SELinux特性

此时,花点时间摆弄一下SELinux系统是值得的,在我们的例子中,我们使用带strict(严格)策略的Fedora Core 4(FC 4)发行版,这些例子大部分都能工作在Red Hat Enterprise Linux 4(RHEL 4)或Fedora Core 5(FC 5),也可能能够工作在其他发行版上,即使它们之间有许多不同之处。附录A”获得SELinux示例策略”描述了如何获取策略文件和其他我们在这本书的示 例中使用到的资源,以及如何使用这些资源来配置你的系统。

运行在Permissive (许可)模式
SELinux可以运行在Permissive 模式,这个模式只存在访问检查,但不会拒绝不允许的访问,它只是简单地进行一个审核操作,这个模式在初次接触SELinux学习时非常有用,你可能想在这 个模式下研究系统,当然,如果你想增强SELinux的访问安全,不应该在正式的系统上使用Permissive 模式,注意/usr/sbin下的某些工具不是使用的常见用户路径。
检查SELinux当前的工作模式最简单的方法是运行getenforce命令,要将系统设置为Permissive 模式,运行setenforce 0,你必须要以root用户在system_t域登陆修改系统为Permissive 模式,要将其修改强制模式,运行setenforce 1,因为你在Permissive 模式,所以只需要以root登陆,将系统修改为强制模式即可。

前面我们已经说过在某些系统命令上添加了-Z选项,如ls和ps分别显示文件和进程的安全上下文,请做一个练习,运行ps xZ和ls -Z /bin命令,检查运行中的进程和可执行文件的安全上下文。

12 重游passwd示例

在这一章中,我们都使用shadow密码文件和密码程序作为例子,如果检查过这两个文件的安全上下文,它们的类型分别应该是shadow_t和 passwd_exec_t,正如前面讨论的,passwd_exec_t是passwd_t域的入口类型,为了证明进程是如何进行域转变的,按照下面的 命令集合进行操作,你需要两个终端窗口或虚拟控制台。
在第一窗口中,运行passwd命令:

启动密码程序,提示输入用户当前的密码,不要输入密码,此时转入第二个终端窗口,在第二个窗口中,su到root用户,然后运行ps命令:

正如你看到的,运行中的密码程序的类型是passwd_t,与前面例子中描述的规则一样。
注意:在strict策略中,普通用户(即在user_t域中运行shell的用户)无权读取大多数/proc/pid条目,因此在ps axZ命令的输出中就看不到passwd程序,这就是为什么我们要su到root的原因了。

SELinux:1. selinux由来

1 什么是SELinux?


     SElinux?(Security Enhanced Linux)安全增强的Linux,美国国防部门在1970-1980年对操作系统安全做了一个安全研究。来自那次安全性研究的关键报告叫做Anderson报告,第一次提出在操作系统中使用访问控制的概念。2000年12月,NSA发布了第一个公开版本。
SELinux 给系统的所有的事物进行标记,包括文件、进程等,通过不同的标记内容和组织的策略实现访问控制。
SELinux

对Linux操作系统的确是一个安全增强。这个增强可以有效地缓解应用软件的缺陷问题,包括那些还没有发现的缺陷。这个增强也实现了许多安全目标,从数据保密性到应用程序完整性到提高的坚固性。使用SELinux,将我们的”城堡”从目前的沙子位置超前移动了一大步。

2 引用监视程序原理



引用在一个引用监视程序中,操作系统将无源的资源隔离到截然不同的客体如文件、运行中的程序活动条目,引用监视程序机制(叫做引用有效机制)将会通过应 用一个嵌入在一套访问控制规则中的安全策略确认在活动主体和客体之间的访问。按照这种方法,程序访问系统资源(如文件)可以被限制到那些符合安全策略的访 问,访问控制决定基于每个活动主体和客体的安全属性,安全属性指活动主体/客体与安全有关的特性。例如:在标准的Linux中,活动主体(即进程)有真实 有效的用户标识,客体(如文件)有访问许可模式,由许可模式决定进程是否可以打开某个文件。
除实现安全策略外,引用监视程序原理最初的设计目标是:

  1. 防止窜改(不能恶意改变或修改)
  2. 无旁路(活动主体不能避免访问控制决定)
  3. 可验证(可以证明安全策略实现是正确的)

几乎所有的操作系统都实现了某种格式的引用监视,都包括活动主体、客体和安全策略规则。在标准的Linux中,活动主体通常是进程,客体通常是用于 信息共享、存储和通讯的系统资源(如文件、目录、套接字、共享内存等)。在Linux中,与其他大多数流行的操作系统一样,安全策略规则通过引用监视程序 (即内核)强制固定和硬编码,无论这些规则的安全属性用于验证什么(如访问模式),都是可以改变和分配的,标准Linux安全是DAC格式的安全。

3 任意访问控制的问题(DAC直接访问控制)


DAC是一种允许经授权的用户(通过它们的程序如一个shell)改变客体的访问控制属性的访问控制机制,由此明确指出其他用户是否有权访问这个客 体。一个简单的DAC形式可能要数文件密码了,访问该文件需要知道文件所有者创建的密码。大多数DAC机制都是基于用户标识的访问控制属性。几乎所有现代 操作系统都有一种基于用户标识的DAC实现。在Linux中,非常流行和广为人知的是所有者-组-其它许可模式机制。同样,常见的访问控制列表机制也是通 用的方法。

所有DAC机制都有一个共同的弱点,就是它们不能识别自然人与计算机程序之间最基本的区别。DAC通常是尝试模仿所有权原理。例如:文件所有者拥有 指定文件的访问权限,只授予可以信任的用户访问文件[4所有者使用它们的辨别力判断是否授予访问权。]。假设你可以信任某个用户(通常被认为是无效的事情),计算机工作方法不是完全模仿的真实世界, 只是按照用户指定的指令在计算机上执行操作,因此,我们不能向用户提供授予和使用访问的能力,相反,我们提供软件程序实现这个功能,在internet时 代变得特别明显,程序总是充满缺陷,或干脆就是恶意程序,这就是特洛伊木马问题,首次是在1970年被认定,到目前的流行病毒、蠕虫、间谍软件,都是它的 变体。简单点说就是,如果一个用户被授权允许访问,意味着程序也被授权访问,如果程序被授权访问,那么恶意程序也将有同样的访问权。

DAC假设一开始所有的程序都是值得信赖且没有缺陷的,早期的计算机研究社团大都是住在高校中的一群人(教师、学生),因此目前发展的技术可能都是 建立在那个假设的环境基础之上的,然而,实际上,我们知道在计算机科学历史上还没有出现过那种开始环境,人类的天性总是喜欢攻击有弱点的软件。

4.强制访问控制的起源


从1970年到1980年,最主要的精力都使用在寻找解决恶意软件或有缺陷的软件的问题上,目标是实现MAC,它的访问控制判断基础不是某个人或系 统管理员的辨别力,我们想实现一种有组织的安全策略来控制对客体的访问,不受个别程序的行为影响。军方在这方面积累了大量的经验,主要是保护政府的机密数 据。大多数常见的MAC机制实现了数据多层安全,图1-2显示了一个多层安全模型的组成结构。

多层安全(MLS)一般都是基于Bell-LaPadula模型[5 http://csrc.nist.gov/publications/history/bell76.pdf],在MLS模型中,所有主体和客体都标记有安全级别,在我们的例子中,我们有 一个PUBLIC和SECRET安全级别,这两个级别代表了数据的敏感程度(SECRET的敏感度比PUBLIC的敏感度要高),在MLS中,主体总是可 以读写客体,除此之外,主体还可以读取底层客体(向下读取),写入高层客体(向上写入),然而,主体可能永远不会读取高层客体(无向上读取),也不写入底 层客体(无向下写入),意思就是信息可以从底层流向高层,但不能反过来,因此要保护高层数据的机密性。

MLS是对访问控制最根本的改变,不再是数据所有者任意地决定谁可以访问客体,此外,对大部分被认为不受信任的软件我们也有足够的安全措施,因为信 息流规则阻止了不正当的数据访问,在MLS中,通过固定的规则决定数据如何共享,而不管用户的请求(更重要的是他们运行的程序),MLS实现了大部分 MAC机制,在目前流行的操作系统中普遍存在,MAC机制与MLS类似,也是经过深思熟虑建立起来的,它实现了小部分固定的安全属性。

MLS的主要弱点是它严格地,以不可改变的方式实现了单一安全目标(即保护政府文件敏感数据的机密性),不是所有的操作系统安全业务都与数据机密性 有关,大多数都对保密政府文件(包括许多处理保密数据的政府系统)的强硬的简单的模型不肯顺从,为了在MLS中扩大这个目标,主体必须被授予安全策略特权 (即违反无旁路的原则),并信任不会违反策略的目的,这个不屈性和有限的焦点使MLS和类似的MAC机制实现了充足的要求

5.更好的强制访问控制


SELinux实现了一个灵活的MAC机制,叫做类型强制(TE),正如你将会看到的,类型强制提供强壮的强制安全能够适应大量的安全目标,类型强 制提供一种思想,将访问控制到对某一个程序级别去,在某种程度上,它允许组织定义适合他们系统的安全策略。在类型强制下,所有主体和客体都有一个类型标识 符与它们关联,要访问某个客体,主体的类型必须为客体的类型进行授权,而不管主体的用户标识符。

使SELinux比MLS解决方案更高级的是规则决定了基于类型的访问控制,这不是预先定义好的,也不是硬编码在内核中的。默认情况下,SELinux不允许任何访问,组织可以开发任意数量的规则指定允许什么,这样使SELinux可以适应非常多样的安全策略。

定义允许访问一个系统收集的规则叫做SELinux策略,物理上,SELinux策略是一个特殊的文件,它包括SELinux内核将会实施的所有规 则,策略文件是从一套源文件编译而来的,正如你马上会看到的,系统与系统之间的SELinux策略是可以不同的,在启动过程中,策略被载入内核,然后内核 就会使用它作为访问控制决定的根据。

注意:在计算机安全领域,术语策略是一个非常大的范围。在这一章中,定义一个组织的安全目标和目的 时我们使用这个术语。然而,在谈到载入内核的SELinux规则集(和包括它们的文件)时也使用策略这个术语。我们尽力避免使用这个词时产生冲突,但不能 完全避免这个问题,如果遇到有歧义的地方,我们通常会明确地编写SELinux策略来避免冲突。

SELinux为Linux带来了灵活的类型强制和一套基于角色的访问控制,以及非强制的MLS。这个灵活性和适应性强的MAC安全已经内置到主流的Linux操作系统中,说明SELinux是如此有希望的提高安全性的技术。

6 SELinux的发展

SELinux起源于自1980开始的微内核和操作系统安全的研究,这两条研究线路最后形成了一个叫做的分布式信任计算机(Distribute Trusted Mach (DTMach))的项目,它融合了早期研究项目的成果(LOCK【锁】,它包含一组安全内核类型强制;Trusted Mach【信任计算机】,它将多层安全控制合并到计算机微内核中)。美国国家安全局的研究组织参加了DTMach项目,付出了巨大努力,并且继续参与了大 量的后续安全微内核项目。最终,这些工作和努力导致了一个新的项目产生,那就是Flask,它支持更丰富的动态类型的强制机制。

由于不同平台对这这项技术没有广泛使用,NAS认为需要在大量的社团中展示这个技术,以说明它的持久生命力,并收集广泛的使用支持意见。在1999 年夏天,NSA开始在Linux内核中实现Flask安全架构,在2000年十二月,NSA发布了这项研究的第一个公共版本,叫做安全增强的Linux。 因为是在主流的操作系统中实现的,所以SELinux开始受到Linux社区的注意,SELinux最迟是在2.2.x内核中以一套内核补丁的形式发布 的。

随着2001年Linux内核高级会议在加拿大渥太华顺利召开,Linux安全模型(LSM[7 http://lsm.immunix.org/])项目开始为Linux内核创建灵活的框架,允许 不同的安全扩展添加到Linux中。NSA和SELinux社区是SELinux的主要贡献者,SELinux帮助LSM实现了大量的需求,为了与LSM 一起工作,NSA开始修改SELinux使用LSM框架。2002年八月LSM核心特性被集成到Linux内核主线,同时被合并到Linux 2.6内核。2003年八月,NSA在开源社区的帮助下,完成了SELinux到LSM框架的迁移,至此,SELinux进入Linux 2.6内核主线,SELinux已经成为一种全功能的LSM模块,包括在核心Linux代码集中。

数个Linux发行版开始在2.6内核中不同程度使用SELinux特性,但最主要是靠Red Hat发起的Fedora Core项目才使SELinux具备企业级应用能力,NSA和Red Hat开始联合集成SELinux,将其作为Fedora Core Linux发行版的一部分。在Red Hat参与之前,SELinux总是作为一个附加的软件包,需要专家级任务才能进行集成。Red Hat开始采取行动让SELinux成为主流发行版的一部分,完成了用户空间工具和服务的修改,默认开启增强的安全保护。从Fedora Core 2开始,SELinux和它的支持基础架构以及工具得到改进。在2005年早些时候,Red Hat发布了它的Enterprise Linux 4(REL 4),在这个版本中,SELinux默认就是完全开启的,SELinux和强制访问控制已经进入了主流操作系统和市场。

SELinux仍然是一个相对较新和复杂的技术,重要的研究和开发在继续不断地改进它的功能。

SElinux 组件

从图中我们可以看到SELinux主要有5个组成部分,其主要部分分别如下:

1 Subject(主体)

访问的发起者(如系统中的进程,读取一个文件作为一个信息流等),是访问客体的进程。

2 Object(客体)

被访问的对象(一个客体的管理者知道请求一个特殊资源(如文件),并能允许其执行这个请求(如在策略允许下对文件进行写操作)),是系统中的一类实体。

3 安全服务器

安全服务器是一种基于安全策略控制主体对客体执行权力的决策者

4 安全策略规则库

安全策略规则库是一个使用SELinux策略语言书写的规则库

5 AVC访问向量缓存

为增加安全服务系统性能,将安全策略存放在缓冲区(cache)