赞
踩
SELinux (Security-Enhanced Linux) 是美国国家安全局(NSA)对于强制访问控制的实现,是 Linux历史上最杰出的新安全子系统。NSA是在Linux社区的帮助下开发了一种访问控制体系,在这种访问控制体系的限制下,进程只能访问那些在他的任务中所需要文件。SELinux 默认安装在 Fedora 和 Red Hat Enterprise Linux 上,也可以作为其他发行版上容易安装的包得到。
SELinux 是 2.6 版本的 Linux 内核中提供的强制访问控制系统,它是一个 Linux 内核模块,也是 Linux 的一个安全子系统。对于可用的 Linux安全模块来说,SELinux 是功能最全面,而且测试最充分的,它是在 20 年的 MAC 研究基础上建立的。
SELinux 在类型强制服务器中合并了多级安全性或一种可选的多类策略,并采用了基于角色的访问控制概念,是一种基于 域-类型 模型(domain-type)的强制访问控制(MAC)安全系统,它由NSA编写并设计成内核模块包含到内核中,相应的某些安全相关的应用也被打了SELinux的补丁,最后还有一个相应的安全策略。SELinux提供了比传统的UNIX权限更好的访问控制。
SELinux 是一个标签系统,这意味着每个进程都有一个标签。每个文件、目录、以及系统对象都有一个标签。策略规则负责控制标签化的进程和标签化的对象之间的访问。由内核强制执行这些规则。
SELinux 主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则)。
在没有使用 SELinux 的操作系统中,决定一个资源是否能被访问的因素是:某个资源是否拥有对应用户的权限(读、写、执行)。只要访问这个资源的进程符合以上的条件就可以被访问。进程理论上所拥有的权限与执行它的用户的权限相同。比如,以root用户启动Browser,那么Browser就有root用户的权限,在Linux系统上能干任何事情。root 用户不受任何管制,系统上任何资源都可以无限制地访问。
在使用了 SELinux 的操作系统中,决定一个资源是否能被访问的因素除了上述因素之外,还需要判断每一类进程是否拥有对某一类资源的访问权限。
这样一来,即使进程是以 root 身份运行的,也需要判断这个进程的类型以及允许访问的资源类型才能决定是否允许访问某个资源,从而只能访问到它所需要的资源。进程的活动空间也可以被压缩到最小。
MAC 机制下,管理员定义好安全策略,用户行为被强制约束,避免发生意外。即使程序出了漏洞、系统受到攻击、进程和用户的权限被剥夺、用户账户泄露等情况下,影响范围也只有在其允许访问的资源范围内,安全性大大增加。
可以看到,在 DAC 模式下,只要相应目录有相应用户的权限,就可以被访问。而在 MAC 模式下,还要受进程允许访问目录范围的限制。
SELinux是通过LSM框架合并到内核中的
1.1 LSM框架
LSM框架的思想是允许安全模块以插件形式进入内核,以便更严格地控制Linux默认的基于身份的任意访问控制(DAC)安全性。LSM在内核系统调用逻辑中提供了一套钩子(hooks),这些钩子通常放在标准Linux访问检查后、且内核调用访问真实资源之前,下图举例说明了LSM框架的基础。
SELinux作为一个LSM模块载入内核,在访问被允许之前进行额外的访问确认。LSM框架的一个分支是只有当标准Linux访问(DAC)检查成功后SELinux才会生效。
1.2 SELinux LSM模块
SELinux LSM模块架构如下图所示:
客体管理器负责对它们管理的资源集强制执行安全服务器的策略决定,对于内核,你可以认为客体管理器是一个内核子系统,它创建并管理内核级客体。内核客体管理器的实例包括文件系统、进程管理和System V进程间通信(IPC)。在LSM架构中,客体管理器是通过LSM钩子描绘的,这些钩子分散在内核子系统各个地方,调用SELinux LSM模块做出访问决定。然后,LSM钩子通过允许或拒绝对内核资源的访问强制执行这些决定。
SELinux架构的第三方组件是访问向量缓存(AVC),AVC缓存是安全服务器为后面的访问检查准备的,目的是为了提升访问确认的速度。AVC还为LSM钩子和内核客体管理器提供了SELinux接口。
Linux中一切皆文件,而操作文件的为进程。进程能发起动作,例如它能打开文件并操作它。而文件只能被进程操作。我们这里可以看做主体对客体进行某种动作。
主体就是想要访问资源目标的源头。想要得到资源,基本流程是这样的:由用户调用命令,由命令产生进程,由进程去访问文件或目录资源。在自主访问控制系统中(Linux 默认权限中),靠权限控制的主体是用户;而在MAC系统中(SELinux 中),靠策略规则控制的主体则是进程。
被主体访问的资源对象,也称为客体。可以是文件、目录、端口、设备等。
对于 SELinux 来说,所选择的策略类型直接决定了使用哪种策略规则来执行主体(进程)可以访问的目标(文件或目录资源)。不仅如此,策略类型还决定需要哪些特定的安全上下文属性。通过策略类型,读者可以更精确地了解 SELinux 所实现的访问控制。
SELinux 提供 3 种不同的策略可供选择,分别是 Targeted、MLS 以及 MiNimum。每个策略分别实现了可满足不同需求的访问控制,因此,为了正确地选择一个满足特定安全需求的策略,就不得不先了解这些策略类型。
Target 策略即目标策略主要对系统中的服务进程进程访问控制,同时,它还可以限制其他进程和用户。服务进程都被放入沙盒,在此环境中,服务进程会被严格限制,以便使通过此类进程所引发的恶意攻击不会影响到其他服务或 Linux 系统。RBAC是基于TE的,而TE也是SELinux中最主要的部分。 type 是此策略下访问决定的主要组成部分。
沙盒(sandbox)是一种环境,在此环境中的进程可以运行,但对其他进程或资源的访问会被严格控制。换句话说,位于沙盒中的各个进程,都只是运行在自己的域(进程所运行的区域被称为“域”)内,它们无法访问其他进程或资源(除非被授予特殊的权限)。
通过使用此策略,可以更加安全地共享打印服务器、文件服务器、Web 服务器或其他服务,同时降低因访问这些服务而对系统中其他资源造成不利影响的风险。
多级安全保护策略,MLS,是 Multi-Level Security 的缩写,该策略会对系统中的所有进程进行控制。启用 MLS 之后,用户即便执行最简单的指令(如 ls)都会报错,这个策略限制得更为严格。
多级安全性方法背后的想法是 SELinux 支持敏感度级别(分层结构)和类别(没有分层相关性)。
敏感度级别是多级安全方法的分层部分。它通常通过公共、内部*、*机密和法规的数据分类敏感性来举例说明,尽管这完全可由管理员配置。使用敏感度标签,启用MLS的系统可以将某些内容标记为具有一定的灵敏度(或灵敏度范围,尽管通常资源使用单个敏感度标签进行标记),并将进程标记为支持灵敏度(或范围,在这种情况下,最高被视为“间隙”,而最低是“当前灵敏度”)。
使用敏感度标签,可以将某些资源(如文档)标记为机密,即使它们具有“标准”类型(如user_home_t)。如果用户只被允许公共和内部敏感级别,他将永远无法阅读此机密文档,即使
多级安全性的第二部分是类别。类别可以看作是分配给资源的标签。类别的示例可以是部门名称(人力资源、基础设施、ICT、销售等)或项目(项目 1、项目 2 等),但也可以完全配置。与敏感度级别不同,类别彼此之间没有任何相关性。
类别的目的是进一步微调级别安全性。如果要授予用户进程对机密文档的访问权限,但只能授予两个部门的访问权限,则可以在机密:销售,ICT的敏感度级别中运行。标有不同类别的其他资源与此敏感度不兼容,因此被拒绝。
SELinux 的 MLS 部分将检查进程的上下文和目标资源的上下文,并查看它们之间的关系。这称为支配地位,有四种可能的回报:
然后,MLS 策略指示在某些权限检查时会发生什么。例如,策略可能会说
仅当域主导资源的上下文时,才允许执行读取操作
仅当域由资源上下文主导时,才允许写入操作数
Minimum 策略即最小限制策略,该策略最初是针对低内存计算机或者设备(比如智能手机)而创建的。
从本质上来说,Minimun 和 Target 类似,不同之处在于,它仅使用基本的策略规则包。对于低内存设备来说,Minumun 策略允许 SELinux 在不消耗过多资源的情况下运行。
无特殊情况下我们一般使用 Target 策略,也更容易理解,MLS 也是在此基础上增加的多级安全保护,本文以下将以 Target 策略为基准进行介绍。
系统中通常有大量的文件和进程,为了节省时间和开销,通常我们只是选择性地对某些进程进行管制,而哪些进程需要管制,要怎么管制是有政策决定的。
一套政策里面有多个规则,部分规则可以按照需求启用或禁用,称为布尔型规则。SELinux根据不同的工作类型对这些规则打开或关闭(on|off<布尔值1|0>),然后通过规则的开启与关闭具体地限制不同进程对文件的读取。
规则是模块化,可扩展的。在安装新的应用程序时,应用程序可以通过添加新的模块(.pp文件)来添加规则,用户也可以手动地使用命令增减规则(.te文件)。
SELinux策略大部分都是一套声明和规则一起定义的类型强制(TE:Type Enforcement)策略,一个定义良好、严格的TE策略可能包括上千个TE规则,TE规则数量的巨大并不令人惊奇,因为它们表达了所有由内核暴露出的允许对资源的访问权,这就意味着每个进程对每个资源的访问尝试都必须至少要有一条允许的TE访问规则,如果我们仔细思考一下现代Linux操作系统中进程和资源的数量,就明白为什么在策略中有那么多的TE规则了。当我们添加由TE规则控制的审核配置和标志时,对于具有严格限制的SELinux策略,常常会见到它包含有上千条规则,在“创建和编写SELinux安全策略”中,我们将会讨论如何创建和管理这些大量的规则,本文旨在理解TE规则是如何工作的。
TE规则的绝对数量对理解SELinux策略是一个大的挑战,但是规则本身并不复杂,它们的分类相对较少,所有的规则基本上都属于两类范畴:
我们使用AV规则允许或审核两个类型之间的访问权,在某些情况下使用类型规则控制默认的标记进行决定。
SELinux的一个重要概念是TE规则是将权限与程序的访问结合在一起,而不是结合用户。所有SELinux策略语言特性都是处理主体(正常的运行中的进程)对客体(文件、目录和套接字等)的访问权的,主要集中于程序访问控制决策,这也是SELinux的主要益处,它允许SELinux策略编写者基于程序的功能和安全属性,加上用户要完成任务需要的所有访问权做出访问决策,可以将程序限制到功能合适,权限最小化的程度,因此,即使它出了故障或被攻击破坏,但整个系统的安全并不会受到威胁。
SELinux是不会管用户的,可以给同一个程序指定多个域类型(因此有不同的特权集),这样就允许引入角色的概念,尽管如此,访问控制的标准仍然是基于程序的域类型而不是用户的特权。焦点是程序的访问权,而不是用户的访问权。selinux 的用户管理中,能跟踪一个登陆用户,即使用户通过 su
命令切换了身份,也被 selinux 视为同一个用户。
安全上下文是SELinux的核心,安全上下文即一种标签
安全上下文分为「进程安全上下文」和「文件安全上下文」
一个「进程安全上下文」一般对应多个「文件安全上下文」
进程安全上下文和文件安全上下文对应上,进程才能访问文件。它们的对应关系由策略中的规则决定。
文件安全上下文由文件创建的位置和创建文件的进程所决定,而且系统有一套默认值,用户也可以对默认值进行设定。
需要注意的是,单纯的移动文件操作并不会改变文件的安全上下文。
安全上下文是 SELinux 的核心,格式由多部分组成:用户、角色、类型标识符、安全等级、安全分类(方括号内为可选项):
格式 | USER:ROLE:TYPE[:LEVEL[:CATEGORY]] |
---|---|
USER 用户 | 常见如:system_u 、root 、user_u |
ROLE 角色 | 常见如:staff_r 、user_r 、object_r 、secadm_r 、sysadm_r 、system_r |
TYPE 类型/域 | TEAC的重要属性,常见名称为**_t,系统资源|进程的type分别称为类型|域(domain) |
LEVEL 安全等级 | 安全等级, 目前已经定义的安全等级为 s0 - s15,等级越来越高 |
CATEGORY 安全分类 | 分类,目前已经定义的分类为 c0 - c1023 |
其中LEVEL和CATEGORY仅在启用MLS后有效
很多系统命令,如 ls
、 ps
、 id
,带有 -Z
参数,可以查看文件/进程的安全上下文。
正如你从术语类型强制猜测的那样,类型是构成TE规则的最小单位,SELinux主要就是使用类型来确定什么访问是被允许的;属性和别名是为减轻管理和使用类型的策略特性,我们使用属性利用单个标识符来引用一组类型。通常,策略语言允许我们在TE规则中类型的适当位置使用属性,而别名允许我们为类型定义另一个名字,别名标识符和类型标识符做同等地位对待。
对于属性:计算机OS中的资源数不胜数、成千上万,如果要对这么多资源分门别类定义不同的类型进行SELinux要实现的访问管理(MAC),那要定义的类型也是极多的。一个大型的,复杂的策略可能包括上万个代表系统上不同资源的类型,例如:Fedora Core 4(FC4)的targeted策略相对较小,但也声明了超过800个类型。当定义新类型时,给其allow权限是一个单调且容易出错的过程。因为上述这种情况,属性出现了,如果说类型是资源的分类,那么属性就是类型的分类。赋予一个属性的访问权限就 等于 赋予访问者所有带有这种属性的类型的资源的访问权限。这代表着,当新增类型时,不需要手动添加allow规则,只需将属性和类型关联即可。
上下文的继承性说明:
如果当前目录下,有一个可执行文件a,那么当我执行./a的时候,进程就会去执行文件a的代码。那么这个启动a的进程是哪一个呢?当我们在命令行下执行./a时,当前所处的shell进程,会fork产生一个子进程,子进程是拷贝了父进程的代码的,那么为了执行a的代码,子进程会使用execve函数,这个函数用a文件的代码替换掉父进程的代码,这样我们a的代码就被执行起来了。而fork出来的子进程,继承了父进程的安全上下文。
对于脚本文件如果使用:解释器+脚本文件名运行 这种方式运行,那么借用的环境将始终不是可执行文件a而是解释器的上下文,即通过解释器执行的脚本再fork进程,而直接指定脚本文件名进行使用则以可执行文件a作为其自身的上下文。
通过bash命令执行vim、mkdir等时新建的安全上下文将继承于当前目录的上下文(根据policy中的规定),这里的“该目录的安全上下文”包含了目录的安全标签以及可能存在的默认安全上下文;而对于特殊的命令如cp命令等除非显式地指定,则新文件的安全上下文将根据目标目录的安全上下文进行调整;对于mv命令则不改变原文件的安全上下文;rmp包安装、tar等则根据包内记录来生成安全上下文,没有记录则根据目标目录重新生成。需要注意的是,有些程序可能会自动更改文件的安全上下文,例如 httpd 守护程序。在这种情况下,可能需要手动更改文件的安全上下文以确保它可以被访问。
SELinux 有三种工作模式,分别是 enforcing
、 permissive
和 disabled
。
enforcing | permissive | disabled |
---|---|---|
强制模式 | 宽容模式 | 关闭SELinux安全策略 |
违反SELinux规则的行为都会被拦截阻止并记录到日志中 | 仅将违反SELinux规则的行为记录到日志中,不会拦截其行为 | 不拦截不记录 |
SELinux 工作模式可以通过 /etc/selinux/config
配置文件中 SELINUX 参数来配置,参考配置:
SELINUX=enforcing | permissive | disabled
这里需要注意的是修改完配置需要重启系统才能生效。
当然,也可以通过 setenforce 1|0
来临时快速切换 enforcing
和 permissive
,并通过 getenforce
或者 sestatus
命令来验证当前状态。
enforcing模式下SELinux的工作流程如图:
当主体想要访问目标客体时,如果系统中启动了 SELinux,则主体的访问请求首先需要和 SELinux 中定义好的策略规则进行匹配。如果进程符合策略中定义好的规则,则允许访问,这时进程的安全上下文就可以和目标的安全上下文进行匹配;如果比较失败,则拒绝访问,并通过 AVC(主要用于记录所有和 SELinux 相关的访问统计信息)生成拒绝访问信息。其中,Target策略下Type是安全过略唯一需要关注的字段。此后,如果安全上下文匹配,则可以正常访问目标文件。当然,最终是否可以真正地访问到目标文件,还要匹配产生进程(主体)的用户是否对目标文件拥有合理的读、写、执行(rwx)权限。
TE策略模型可以概述为:P = ST x OPT x TT:许可权限§ = 原类型(ST)对目标类型(TT)的资源类(class)的操作(OPT)
当查看特定安全上下文的策略规则时,SELinux 会使用被称为 AVC(Access Vector Cache,访问矢量缓存)的缓存,如果访问被拒绝(也被称为 AVC 拒绝),则会在一个日志文件中记录下拒绝消息。
SELinux有大量的工具记录日志信息,或审核、访问尝试被策略允许或拒绝的信息。审核消息通常叫做"AVC消息",它提供了详细了关于访问尝试的信息,包括是允许还是拒绝,源和目标的安全上下文,以及其它一些访问尝试涉及到资源信息。AVC消息与其它内核消息类似,都是存储在/var/log目录下的日志文件中,它是策略开发、系统管理和系统监视不可缺少的工具。在此,我们检查是哪一个访问尝试产生了审核消息。
默认情况下,SELinux不会记录任何允许的访问检查,只会记录被拒绝的访问检查。这并没什么奇怪的,在大多数系统上,每秒会允许成千上万的访问,只有很少的一部分会被拒绝,允许的访问通常是在预料之中的,通常不需要审核,被拒绝的访问通常是(但不总是)非预期的访问,对它们进行审核便于管理员发现策略的bug和可能的入侵尝试。策略语言允许我们取消这些默认的预料之中的拒绝审核消息,改为记录允许的访问尝试审核消息。
这些被拒绝的消息可以帮助诊断和解决常规的 SELinux 策略违规行为,至于这些拒绝消息到底被记录在什么位置,则取决于 auditd 和 rsyslogd 守护进程的状态:
注意,如果 auditd 和 rsyslogd 都在运行,那么拒绝消息将发送到 audit.log 和 messages 日志文件中。
通常使用 audit2why
、 audit2allow
和 sealert
命令来调试AVC拒绝日志。
整体翻译:SELinux拒绝PID为6591且httpd_t类型的httpd进程从nfs_t类型的目录读取数据。
type=AVC msg=audit(1395177286.929:1638): avc: denied { read } for
pid=6591 comm="httpd" name="webpages" dev="0:37" ino=2112
scontext=system_u:system_r:httpd_t:s0
tcontext=system_u:object_r:nfs_t:s0
tclass=dir permissive=0
整体翻译:SELinux拒绝PID为6591且httpd_t类型的httpd进程从nfs_t类型的目录读取数据。
各个参数详解
type=AVC
日志类型,该日志仅仅在audit.log文件中现实,它告诉用户该审计日志的具体类型。本例中类型为AVC。
msg=audit(1395177286.929:1638)
时间戳,起始于1970年1月1日的记秒数。当然,我们可以通过date命令将其转换为墙钟时间。
avc:
日志类型,这里有些重复了。SELinux 执行并记录在访问向量缓存 (AVC) 中的操作
denied
SELinux采取的动作,可以是denied或者granted。如果系统配置的是permissive模式,那么虽然SELinx会放行,但在审计日志中仍然是denied。
{ read }
被拒绝的动作。有getattr, read,write.等。本例中是一个读请求。有时请求的类型可能不止一个,比如{ read write },但通常只有一个。
for pid=6591
尝试执行拒绝操作的主体的进程标识符,期望获取许可的进程ID信息。
comm=“httpd”
用于调用分析进程的命令名称。有些进程我们无法获得进程的ID,因此可以通过该参数获得具体是那个进程。
name=“webpages”
目标的名称,本例中是一个文件名称。
dev=“0:37”
目标所位于的设备。如dev="sysfs"文件所在的位置应该是/sys目录
ino=2112
目标文件的inode id。可以根据该id获得文件的具体路径。
scontext=system_u:system_r:httpd_t:s0
源/主体上下文,进程(访问者)的安全上下文。这里其实就是关于SELinux访问者的标签信息,SELinux正是根据源和目的标签及策略来实现访问控制的。
tcontext=system_u:object_r:nfs_t:s0
目的/客体上下文,目标资源(被访问者)的安全上下文。
tclass=dir
目标/客体对象类,本例是目录。SELinux支持的类型很多,比如文件、套接字或者信号量等等。
permissive=0
上述操作是否通过,为0则拒绝操作,为1则操作放行。
在启动时改变 SELinux 模式的内核参数有:
autorelabel=1 → 强制给系统重新标签化
selinux=1 → 内核不加载 SELinux 基础设施的任何部分
enforcing=0 → 以许可permissive模式启动
sestatus [参数]
参数:
-v : 详细检查进程和文件的安全上下文
-b : 显示当前布尔值状态
命令输出信息说明
以下输出是在 ubuntu 20.04 上的 sestatus 命令:
SELinux status:表示系统上是否启用SELinux模块
SELinuxfs mount:这是SELinux临时文件系统的挂载点,这是SELinux内部使用的,可以使用ls命令查看该目录,如: ll /sys/fs/selinux/
SELinux root directory:这是所有SELinux配置文件所在的位置,该目录包含SELinux所需的所有配置文件,我们可以修改这些文件
Loaded policy name:这表示当前加载的SELinux策略类型,默认情况下加载的策略类型为targeted(default)
Current mode:表示SELinux当前执行的策略模式enforcing、permissive、diabled
Policy MLS status: 指示MLS策略的当前状态,默认情况下将启用
Policy deny_unknown status: 指示我们策略中deny_unknown标志的当前状态,默认情况下,它将设置为允许
Max kernel policy version: 指示我们中包含的SELinux策略的当前版本,在此示例中,它是版本33
seinfo [参数]
#seinfo 每次生成的查询结果可能顺序不同
[无参数] | -b | -h |
---|---|---|
列出SELinux的版本、执行策略和规则布尔值、身份识别、角色、类型等所有的数量信息 | 列出所有规则的种类(布尔值) | 命令帮助 |
seinfo [参数[ 指定对象 -x]]
-u | -r | -t |
---|---|---|
列出SELinux所有身份识别(user)的种类 | 列出SELinux所有角色(role)的种类 | 列出SELinux所有类型(type)的种类 |
查询某个用户user关联了哪些selinux的user以及role | 查询某个角色关联的类型信息 | 查询一个type所属于的所有domain的信息 |
-a | -c |
---|---|
列出SELinux所有属性(attribute)的种类 | 列出SELinux所有类别(class)的种类 |
查询某个属性attribute关联了哪些selinux的type | 查询某个类别(class)具备的许可类型 |
sesearch [OPTIONS] RULE_TYPE [RULE_TYPE ...] [EXPRESSION] [POLICY ...] OPTIONS: -d, --direct 不搜索 type 的属性 -R, --regex 使用正则表达式进行匹配 -n, --linenum 显示每条可用规则的行号 -S, --semantic 搜索语义(semantically)规则替代语法(syntactically)规则 -C, --show_cond 显示条件规则的条件表达式 -h, --help 帮助信息 -V, --version 版本号 RULE_TYPES: -A, --allow 允许(allow)的规则 --neverallow 从不允许(neverallow)的规则 --auditallow 审计(auditallow)的规则 -D, --dontaudit 不审计的规则 -T, --type type_transition, type_member, 和 type_change 规则 --role_allow 角色允许的规则 --role_tans role_transition 规则 --range_trans range_transition 规则 --all 所有规则,不论是:type, class, 或 perms EXPRESSIONS: -s NAME, --source=NAME 具有类型、属性值为 NAME 的规则作为源头(进程主体的概念) -t NAME, --target=NAME 具有类型、属性值为 NAME 的规则作为目标(文件,端口等类型的概念) --role_source=NAME 具有角色值为 NAME 的规则作为源头 --role_target=NAME 具有角色值为 NAME 的规则作为目标 -c NAME, --class=NAME 具有 class 值为 NAME 的规则作为对象类 -p P1[,P2,...], --perm=P1[,P2,...] 具有特定权限的规则 -b NAME, --bool=NAME 具有 NAME 值在表达式中的条件规则
通用选项 | 含义 |
---|---|
-l 或 --list | 查询选项 |
-a | 添加 |
-d | 删除指定的默认配置 |
-m | 修改指定的默认配置 |
-h 或 --help | 选项说明帮助 |
-o [filename] | 导出selinux当前策略 |
-i [filename] | 导入selinux当前策略 |
-n | 不打印说明头 |
-D | 全部删除 |
查询选项命令
semanage [选项对象] -l
选项对象:
login | user | port | interface | fcontext | node |
translation | permissive | boolean | import | export | dontaudit
重要选项对象说明:
[ login ] - linux用户和selinux用户user登录映射管理
semanage login -{a|d|m|l|n|D} [-sr] login_name
-s: SELinux user名
-r: MLS/MCS的限制范围,以双引号包含,如: "s0-s0"或"s0-s0:c0.c1023"
#usermod -Z seuser user 具有类似作用(需在selinux-enable下使用)
[ user] - SELinux用户角色和MLS/MCS级别(LEVEL)之间的映射管理
semanage user -{a|d|m|l|n|D} [-LrRP] selinux_name
selinux_name:selinux-user名
-R:selinux Roles 指定角色,以双引号和空格分离
-P:selinux Prefix 前缀(链接到selinux 用户id,并反映用户角色)
-L:selinux缺省的level(MLS/MCS级别),如: -L s0
-r:MLS/MCS的限制范围,以双引号包含,如: "s0-s0"或"s0-s0:c0.c1023"
[ fcontext ] - 文件安全上下文的默认设置
semanage fcontext -{a|d|m|l|n|D} [-frst arguments] file_spec file_spec:文件描述,双引号括住时可支持正则表达式,如:"/web(/.*)?" -f:file type, 描述文件类型,用法: -f {a,f,d,c,b,s,l,p} a: all files 全部文件(未指定-f时默认此选项) f: regular file 普通文件 d: directory 目录 c: character device 字符设备 b: block device 块设备 s: socket 套接字 l: symbolic link 软链接 p: named pipe 命名管道 -r:role 角色 -s:source type(进程主体的概念) -t:target type(文件,端口等类型的概念) #semanage fcontext仅设置对象标签(无论存不存在或即将存在),不会立即改变上下文 #".*"指代所有子文件及目录,如/.*为根目录下所有对象而/var.*为单个对象 #单独的.点号需要反斜杠\来转义,如/etc/ulogd\.conf #该命令带有(/.*)?时,仅设置对应目录以及未来新的文件/目录的上下文,已存在上下文的对象或者有其他同命令固定指定的对象则不会改变,如指定/etc/myetc(/.*)?且/etc(/.*)?,则范围大的指令/etc(/.*)?不会改变myetc的上下文 #已存在目录下的子文件/目录的上下文可以在此后通过restorecon立即更新 #同一个file_spec对象只能存在一个标签,默认的seuser为system_u
[ permissive ] - 特定类型的工作模式管理
semanage permissive -{a|d|l|n|D} type
单独将某些类型设置为permissive,也就是说,整个系统运行在enforce模式时,此类型是permissive的
[ dontaudit ] - 规则的审计管理
semanage dontaudit [ on | off ]
[ boolean ] - 布尔规则的管理
semanage boolean -{d|D|m|l|n|N} -[-on|-off|1|0] boolean_name
-d:delete 删除规则
-D:--deleteall,删除所有规则
-m:modify 更改规则
-n:--noheading,不打印说明头
-N:--noreload,不加载规则
getsebool -a
getsebool rulename
获取某个或所有布尔规则的状态
setsebool [-P] rulename on/off
临时设定某个布尔规则的状态,打开或关闭
-P:permanent,永久设定(semanage boolean仅能临时设置)
chcon [选项] 文件或目录 选项: -H:如果命令行参数是一个通到目录的符号链接,则遍历符号链接 -L:遍历每一个遇到的通到目录的符号链接 -P:不遍历任何符号链接(默认) --help:显示此帮助信息并退出 --version:显示版本信息并退出 -h, --no-dereference:影响符号连接而非引用的文 --reference=参考文件:使用指定参考文件的安全环境,而非指定值 -R, --recursive:递归处理所有的文件及子目录 -v, --verbose:为处理的所有文件显示诊断信息 -u, --user=用户:设置指定用户的目标安全环境 -r, --role=角色:设置指定角色的目标安全环境 -t, --type=类型:设置指定类型的目标安全环境 -l, --range=范围:设置指定范围的目标安全环境 #chcon仅能改变已存在对象的上下文,且立即改变无需restorecon #而semanage focontext则是设置默认的上下文,其甚至能设置当下不存在以及未来新建或者拷贝而来的新对象 #chcon改变的对象,会被semanage fcontext的规则(若存在)在restorecon或者重启系统时覆盖
restorecon [-iFnrRv] [-e excludedir ] [-o filename ] [-f filename | pathname...]
-i:忽略不存在的文件
-f:infilename 文件,infilename 中记录要处理的文件
-e:directory 排除目录
-R/-r:递归处理目录
-n:不改变文件标签
-o/outfilename:保存文件列表到 outfilename,在文件不正确情况下
-v:将过程显示到屏幕上
-F:强制恢复文件安全语境
auditctl [选项]
选项 | 含义 |
---|---|
-e <启用标志> | 设置启用标志,禁用或启用内核审计功能,标志0是禁用,1是启用 |
-a <列表名称,动作> | 向列表末尾添加规则 |
-A <列表名称,动作> | 向列表开头添加规则 |
-c | 加载规则时尽管错误仍旧继续 |
-S <系统调用名|编号|all> | 生成规则:系统调用的名称或者编号 |
-F <字段名> | 建立一个规则字段:名称、操作、值 |
-w <路径> | 在指定路径插入一个记录器 |
-p <权限> | 设置文件权限,r表示读取,w表示写入,x表示执行,a表示更改属性 |
-k <关键词> | 设置审计规则上的过滤关键词,关键词时不超过32字节长的任意字符串 |
-D | 删除所有规则 |
-s | 报告内核的审计子系统状态 |
-l | 列出所有规则 |
-R <文件> | 从文件中读取规则 |
-m <文本> | 发送用户空间信息到审计系统 |
-i | 从文件中读取队则时忽略错误 |
-f <故障标志位> | 设置故障标志位,有0、1、2三个值,0是不输出日志,1为输出printk日志,2会大量输出日志信息 |
-r <发送率> | 设置每秒消息的发送率 |
-b <缓冲区最大值> | 设置audit缓冲区最大值 |
-d | 删除规则 |
-a/-A选项:列表名称 | 描述 |
---|---|
task | 添加规则到每个人物列表,只有在创建时就已知的字段(如UID/GID)才可以用在这个列表中 |
exclude | 添加规则到事件类型排除过滤列表,使用此列表来过滤不希望看到的事件 |
exit | 添加规则到系统调用退出列表,退出系统时调用此列表用于确定是否应建立审计事件 |
user | 添加规则到用户消息过滤列表,内核在将用户空间事件传递给审计守护进程之前使用这个列表过滤用户空间事件,有效的字段只有UID、AUID、GID、PID、subj_user、subj_role、subj_type、subj_sen、subj_clr |
-a/-A选项:动作 | 描述 |
---|---|
never | 不生成审计记录,可以被用来抑制事件生成 |
always | 分配审计上下文,总是把它填充在系统调用条目中,总是在系统调用退出时写一个审计记录 |
-F选项:字段名 | 描述 |
---|---|
pid | 进程ID |
ppid | 父进程的进程ID |
uid | 用户ID |
euid | 有效用户ID |
suid | 保存的用户ID |
fsuid | 文件系统用户ID |
gid | 组群ID |
egid | 有效组群ID |
sgid | 保存的组群ID |
fsgid | 文件系统组ID |
msgtype | 用来匹配事件的记录类型 |
pers | 操作系统个性编码 |
path | 查看文件的完整路径 |
arch | 系统调用的CPU体系结构 |
auid | 审计ID,用户登录时使用的原始ID |
dir | 查看目录的完整路径 |
devmajor | 主设备号 |
devminor | 次设备号 |
inode | inode号 |
exit | 系统调用的返回值 |
success | 系统调用的成功值,1表示true/yes,0表示false/no |
a0、a1、a2、a3 | 分别表示系统调用的前四个参数,只能用数字表示 |
key | 设置用来标记事件的审计日志事件消息的过滤关键字 |
perm | 文件操作的权限过滤 |
fieltype | 目标文件的类型 |
obj_user | 对象的SELinux用户 |
obj_role | 对象的SELinux角色 |
obj_type | 对象的SELinux类型 |
obj_lev_low | 资源的SELinux低级别 |
obj_lev_high | 资源的SELinux高级别 |
subj_sen | 程序的SELinux敏感度 |
subj_user | 程序的SELinux用户 |
subj_clr | 程序的SELinux清除率 |
subj_role | 程序的SELinux角色 |
subj_type | 程序的SELinux类型 |
ausearch [选项 [基于对象的搜索]]
如:
ausearch -ui 0 #基于用户root的审计搜索
ausearch -tm tty1 #基于终端tty1审计搜索
ausearch -p 1779 #基于进程号1779审计搜索
ausearch -m avc -ts #基于近期的AVC消息
选项 | 选项 | 选项 |
---|---|---|
-f <文件名> | -hn <主机名> | -p <进程ID> |
-c <命令行名称> | -ui <用户UID> | -n <计算机名称> |
-ga <所有组群的ID> | -tm <终端> | -sv <系统调用或事件成功值> |
-k <键字段> | -m <消息类型> | -pp <父进程ID> |
-ul <用户登录ID> | -x <可执行文件名> | -a <审计事件ID> |
-ue <有效UID> | -ge <有效GID> | –session <登录会话ID> |
-sc <系统调用名称或对象编号> | -se <SELinux任何主体上下文> | -ts <开始日期><开始时间> |
-ua <所有用户UID> | -o <SELinux对象上下文> | -su <SELinux主体上下文> |
-e <系统调用退出代码> | -r (完全未格式化输出) | -i (将数据格式转化为可读文本格式) |
aureport [选项]
-i: 将数据格式转化为可读文本格式
-l: 生成登录事件报告
-u: 生成用户的事件报告
-e: 生成事件报告
-p: 生成进程事件报告
-s: 生成系统调用报告
-x: 生成可执行的相关报告
-f [file]: 生成一个(指定的)文件相关的报告
-t: 查看 audit log文件包含日志的起止时间
-ts start_time: 指定start_time之后时间内的信息
-te end_time: 指定end_time之前时间内的信息
--failed: 指定失败的事件进行统计
--summary: 针对总体各类型进行数量统计
autrace [参数] [程序]
参数:
-r: 限制收集到分析资源使用情况所需的系统调用
如: autrace -r /bin/ls /root
autrace生成的log也会存放在/var/log/audit/audit.log
当用autrace去跟踪一个进程时,为了保证避免autrace与之前audit rule生成的日志冲突,使用auditctl -D去停止所有的audit log,当autrace结束后,使用systemctl restart auditd重启audit服务
audit2why 命令用来分析 audit.log 日志文件,并分析 SELinux 为什么会拒绝进程的访问。也就是说,这个命令显示的都是 SELinux 的拒绝访问信息,而正确的信息会被忽略。命令的格式也非常简单
audit2why < 日志文件名 #通常直接使用/var/log/audit/audit.log
#输出的建议规划是以TE语言写的 audit2allow [options] Options: --version show program's version number and exit -h, --help show this help message and exit -b, --boot audit messages since last boot conflicts with -i -a, --all read input from audit log - conflicts with -i -p POLICY, --policy=POLICY Policy file to use for analysis -d, --dmesg read input from dmesg - conflicts with --all and --input -i INPUT, --input=INPUT read input from <input> - conflicts with -a -l, --lastreload read input only after the last reload -r, --requires generate require statements for rules -m MODULE, --module=MODULE set the module name - implies --requires -M MODULE_PACKAGE, --module-package=MODULE_PACKAGE generate a module package - conflicts with -o and -m -o OUTPUT, --output=OUTPUT append output to <filename>, conflicts with -M -D, --dontaudit generate policy with dontaudit rules -R, --reference generate refpolicy style output -N, --noreference do not generate refpolicy style output -v, --verbose explain generated output -e, --explain fully explain generated output -t TYPE, --type=TYPE only process messages with a type that matches this regex --perm-map=PERM_MAP file name of perm map --interface-info=INTERFACE_INFO file name of interface information --debug leave generated modules for -M -w, --why Translates SELinux audit messages into a description of why the access was denied
audit2allow -i 日志文件名 [-o 输出的建议文件名]
audit2allow -i 日志文件名 [> 输出的建议文件名]
sealert 命令是 setroubleshoot 客户端工具,也就是 SELinux 信息诊断客户端工具。虽然 setroubleshoot 服务已经不存在了,但是 sealert 命令还是可以使用的。
sealert [选项] 日志文件名
#选项:
#-a: 分析指定的日志文件;
semodule命令的作用是可以管理SELinux策略模块,比如显示、安装、重装、升级、删除、激活及禁用策略模块。
semodule命令还可用于强制从模块存储重建策略和/或强制重新加载策略而不执行任何其他事务。 semodule命令作用于semodule_package创建的模块包。通常,这些文件具有.pp后缀(策略包),尽管这不是以任何方式强制执行的。
semodule [选项 [选项对象]] 选项: -R,-reload : 强制重新加载策略模块 -l,-list-modules : 显示已安装模块的列表(基本除外) -B,--build : 强制重建策略(除非使用-n,否则重新加载) -D,--disable_dontaudit Remove dontaudits from policy -X,--priority=PRIORITY set priority for following operations (1-999) -E,--extract=MODULE_NAME extract module -n,--noreload : 提交后不要重新加载策略 -v,--verbose : 冗长打印 -i,--install= : 安装/更换模块包 -u,--upgrade= : 升级现有模块包,或者如果模块不存在则安装 -e,--enable= : 启用现有模块 -d,--disable= : 禁用现有模块 -b,--base= : 安装/更换基础模块包 -r,--remove= : 删除现有模块 -P,--preserve_tunables Preserve tunables in policy -C,--ignore-module-cache Rebuild CIL modules compiled from HLL files -p,--path use an alternate path for the policy root -S,--store-path use an alternate path for the policy store root -c, --cil extract module as cil. This only affects module extraction. -H, --hll extract module as hll. This only affects module extraction. -s,--store name of the store to operate on -N,-n,--noreload do not reload policy after commit -h,--help print this message and quit #加载的模块直接写入内核,无需保留原.pp文件
checkmodule 是一个程序,用于检查 SELinux 安全策略模块并将其编译为二进制表示形式。它可以生成基本策略 模块(默认)或非基本策略模块(-m 选项);通常,您将构建一个非基本策略模块以添加到已 具有基本策略提供的基本模块。使用 semodule_package 将此模块与其可选文件上下文组合以创建策略包,然后 使用 SEemu 将模块包安装到模块存储中并加载生成的策略。
checkmodule [-h] [-b] [-m] [-M] [-U handle_unknown ] [-V] [-o output_file] [input_file]
选项说明:
-b,--binary : 读取现有的二进制策略模块文件,而不是源策略模块文件,此选项是开发/调试辅助工具
-h,--help : 打印使用情况帮助
-m : 生成非基本策略模块
-M,--MLS : 在检查和编译策略模块时启用 MLS/MCS 支持
-V,--version : 显示此程序创建的策略版本
-o,--output : 将二进制策略模块文件写入指定的文件名,否则checkmodule 只会检查模块源文件的语法,不会生成一个二进制模块
-U,--handle-unknown <action> : 指定内核应如何处理未知类或权限(deny, allow or reject)
semodule_package 是用于从二进制策略模块和可选的其他数据(如文件上下文)创建 SELinux 策略模块包的工具,semodule_package打包由检查模块创建的二进制策略模块,然后可以通过semodule安装创建的策略包
semodule_package -o <输出文件> -m <模块> [-f <文件上下文文件>]
选项说明:
-o,--outfile <output file> : 指定此工具生成的策略模块包文件名
-s,--seuser <seuser file> : 要包含在包中的seuser文件
-u,--user_extra <user extra file> : user_extra要包含在包中的用户额外文件
-m,--module <Module file> : 要包含在包中的策略模块文件
-f,--fc <File context file> : 模块的文件上下文文件(可选)
-n,--nc <netfilter context file> : 要包含在包中的网络过滤器上下文文件
newrole [-r|--role] ROLE [[-t|--type] TYPE] [[-l|--level] LEVEL]
#在当前bash等中切换当前user的其他角色
getseuser linuxuser from_context
getconlist [-l level] selinux_user [context]
与shell脚本相同,行首添加#
井号注释此行
define ('x', '值、集或描述语句')
# 可以使用$1、$2等按顺序表示函数宏的入参
如: 定义file_type_trans(domain, dir_type, file_type)宏
define(`file_type_trans', `
allow $1 $2:dir ra_dir_perms;
allow $1 $3:notdevfile_class_set create_file_perms;
allow $1 $3:dir create_dir_perms;
')
require {
[\tab]type a;
[\tab]attribute b;
[\tab]class b { permset };
}
#注意引用但未使用可能导致模块出错
#引用的客体类型中必须包含其同时引用的操作许可,调用未引用的许可也会出错,使用通配符*时其仅代表被引用过的所有许可
type 类型名称 [alias 别名集] [,属性集]
attribute 属性名称
属性和类型,别名都在同一个命名空间,因此不能与其他类型或别名重名。
属性声明在整个策略,基础载入模块和非基础载入模块中都有效,但在有条件的语句中无效。
一个类型可以有多个属性,一个属性可以囊括多个类型;在声明、关联一个属性时,会自动向具有此属性的类型组中所有类型进行声明、关联。
typeattribute 类型名 属性名
一个或多个事先声明的属性标识符,如果指出多个属性标识符,属性标识符之间使用逗号分隔,如typeattribute bin_t file_type, exec_type;
typeattribute语句在单个策略,基础载入模块和非基础载入模块中都是有效的,只有在条件语句中无效。
typeattribute允许我们在一个地方type定义类型,在另一个地方再关联属性,增强了语言的灵活性。
typealias 类型名称 alias 别名名称
类型名称:要添加别名的类型的名称,类型必须使用type语句单独声明,而且这里只能指定一个类型名称。
别名名称:如果同时指定多个别名,别名之间用空格分开,并使用大括号将所有别名括起来,如{aliasa_t aliasb_t}。
typealias语句在单个策略,基础载入模块和非基础载入模块中都有效,只有在条件语句中无效。
命令名称 源类型集 目标类型集 : 客体类别集 操作许可集
命令名称
类型集
源类型集:授予访问的类型和(或)属性,通常是进程的域类型
目标类型集:客体的类型和(或)属性,源类型被授权可以访问的类型
按集使用时用空格进行分隔,并使用大括号将它们括起来,如{bin_t sbin_t}。
客体类别集
一个或多个客体类别(Object Class),多个客体类别必须使用大括号括起来,如{file lnk_file}。
操作许可集
表示主体对客体访问时允许的操作类型(也叫做访问向量),所有许可(PermSet)对类别集列出的所有客体类别都要有效。如{read execute create}。
类型规则在创建客体或在运行过程中重新标记时指定其默认类型,它仅提供一个新的默认类型标记
命令名称 源类型集 目标类型集 : 类别集 单个默认类型
type_transition规则没有allow访问权,它仅提供一个新的默认类型标记,要成功进行类型转换,也必须要一套相关联的allow规则,以允许进程类型可以创建客体和标记客体。此外,默认的标记指定在type_transition规则中了,只有创建进程没有明确地覆盖默认标记行为它才有效。
# 如: 这条域转换规则(类别为process)
type_transition a_t b_t : process c_t;
#解释: 当a_t Domain中的进程执行type为b_t类型的可执行文件(fork并execv)时,其class(此处是process)所属Domain(对process而言,肯定是指Domain)需要切换到c_t域
# 至少需要下面三条allow规则才能成功
#首先,你得让a_t域中的进程能够执行type为b_t的文件
allow a_t b_t : file execute;
#然后,你还得告诉SELiux,允许a_t做DT切换以进入c_t域
allow a_t c_t : process transition;
#最后,你还得告诉SELinux,切换入口(对应为entrypoint权限)为执行b_t类型的文件
allow c_t b_t : file entrypoint;
域转换(客体类别为类别为process)最关键的概念是清楚地定义了入口点,即类型为c_t的文件对新的默认类型b_t有entrypoint许可,入口点文件允许我们严格控制哪个程序可以在哪个域中执行(可以认为这就是类型强制的安全特性),我们知道只有程序的可执行文件的类型对域有entrypoint许可时,这个程序才可以进入一个给定的域,因此我们可以知道并控制哪个程序有哪个特权了。要做DT,肯定需要先fork一个子进程,然后通过execv打开一个新的可执行文件,从而进入变成那个可执行文件对应的活物!所以,在type_transition语句中,target_type往往是那个可执行文件(死物)的type。default_type则表示execv执行后,这个活物默认的Domain。
某些情况下不能使用客体转换(使用与文件系统有关的客体类别集如file,dir,lnk_file等)规则,当进程需要在同一个客体容器中创建有多个不同类型的客体时,一条type_transition规则还不够,例如:假设一个进程在/tmp/目录下创建两个UNIX域套接字,这些套接字将用于和其它域通信,如果我们想给每个sock文件不同的类型,客体转换规则将不能满足了,这时需要两条规则,它们有相同的源类型,目标类型和客体类别,只是默认类型不同,但这样会在编译时产生错误,解决这个问题的办法是在安装时创建sock文件,并明确地标记它们,将sock文件分别放在不同目录类型的目录下,或让进程在创建时明确地请求类型。
我们可能很少使用type_change规则,因为它们通常只由核心操作系统服务使用。
class 类别名 [inherits 通用许可集名] [{许可集}]
common 通用名 {许可集}
声明许可有两种方法,第一种叫做通用许可(被多个客体类别所共用),它允许我们创建与客体类别一起作为一个组的许可,通用许可在类似的客体类别(如文件和符号连接)共享一套访问许可时很有用;第二种方法叫做特定类别许可(由某个客体类别所独用),它允许我们单独为客体类别声明特定的许可,通过class声明。正如将会看到的,有一些客体类别只有特定的许可,有一些只有通用许可,还有一些是这两者都有。
role 角色名称 types [类型 类型集];
#仅role定义角色,当附带types类型时不为定义语句而作为关联语句使用(如typeattribute)
role_transition 角色集 类型集 目标角色
这个规则说明,当一个角色集的进程获取对应类型集的资源时,SELinux将会尝试将起转换为目标角色。
角色转换规则指定了执行一个文件时默认的角色变化,角色转换规则没有允许访问权,要成功转换角色,角色allow规则也是必须的:
allow 原角色 目标角色;
#允许角色作转换
dominance {role 角色名称 {[role 角色;]*n}}
#Warning: role 'dominance' statement may be unsupported in CIL. Dropping from output.
角色控制语句(dominance)按照其他角色声明一个角色,我们可以使用这个语句创建一个角色之间的层次关系,"高层角色"会自动继承所有与角色关联的类型,注意任何dominance控制语句后添加给高层角色的类型并不会继承下来。
一个或多个以“role 角色名称”形式指定的角色,多个角色之间使用空格分隔,如
dominance {role staff_r; role sysadm_r;}
策略语言不支持更复杂的语法,这里的角色集可以包括嵌套的控制关系定义,使用大括号进行表示,如:
dominance { role a_r { role b_r; role c_r { role d_r; } } }
#在这个例子中,角色定义如下:
# d_r 只有它自己的类型
# c_r 它的类型和d_r的类型
# b_r 只有它自己的类型
# a_r 它自己的类型和所有b_r,c_r和d_r的类型
策略语言中可以使用 self
、 -
、 *
和 ~
通配符:
-
来排除一个属性中的类型或属性中的类型,如 {exec_type -sbin_t};
。其中还包含了一个特殊操作符 self
: 使用语句中原类型的别名 self 作为目标类型即目标类型==源类型。在目标类型区域可以使用关键字 self
,但在源类型区域不能使用,如:allow domain self : process signal;
。*
,其包括了客体类别的所有许可;其次是求补算操作符 ~
,即除了列出的许可外,其它的许可都包括。如:allow user_t bin_t : { file dir } *;
和 allow user_t bin_t : file ~{ write setattr ioctl };
# genfscon定于文件系统上下文
genfscon fs_type pathprefix [-file_type] context
#把/proc/mtk_demo/demo_file文件的安全上下文设置成demo_context
genfscon proc /mtk_demo/demo_file u:object_r:demo_context:s0
# portcon定义端口的上下文
portcon tcp 80 system_u:object_r:http_port_t
portcon tcp 8080 system_u:object_r:http_port_t
# netifcon定义网络接口的上下文
netifcon eth0 system_u:object_r:netif_eth0_t system_u:object_r:netmsg_eth0_t
# nodecon定义节点的上下文
nodecon 10.33.10.66 255.255.255.255 system_u:object_r:node_zeus_t;
nodecon 10.33.10.0 255.255.255.0 system_u:object_r:node_any_t
#文件名加te后缀
#文件顶部开头用
#定义模块名 module_name ,需要与文件名 module_name.te 相同
policy_module(module_name, 1.0); #或者: module linux_user 1.0;
#创建用户模板的模块大致如下编写:(部分系统不支持)
userdom_login_user_template(linux_user);
userdom_login_user_template
作用为创建登录用户的模板,非特权,相当于linux的普通用户。创建系统管理员sysadm时调用 userdom_admin_user_template
创建特权用户模板。
客体类别和许可定义如下(客体类别定义见kernel/security/selinux/include/classmap.h):
客体类别 | 描述 |
---|---|
filesystem | 文件系统(如一个真实的分区) |
file | 普通文件 |
dir | 目录 |
fd | 文件描述符 |
lnk_file | 符号链接 |
chr_file | 字符文件 |
blk_file | 块文件 |
sock_file | UNIX域套接字 |
fifo_file | 命名管道 |
客体类别 | 描述 |
---|---|
socket | 其他的套接字 |
tcp_socket | TCP套接字 |
udp_socket | UDP套接字 |
rawip_socket | 发送原始IP数据包的套接字 |
node | 代表一个IP地址或一段IP地址的主机 |
netif | 网络接口(如eth0) |
netlink_socket | 所有其它的Netlink套接字 |
packet_socket | 发送其它类型的原始数据包的套接字 |
key_socket | PF_KEY协议家族的套接字,用于管理IPsec中的密钥 |
unix_stream_socket | 本地机器上(unix域)的IPC流套接字 |
unix_dgram_socket | 本地机器上(unix域)的IPC数据报套接字 |
netlink_route_socket | 用于控制和管理网络资源如路由表和IP地址的Netlink套接字 |
netlink_firewall_socket | 用于创建用户空间防火墙过滤器的Netlink套接字 |
netlink_tcpdiag_socket | 用于监视TCP连接的Netlink套接字 |
netlink_nflog_socket | 用于接收Netfilter日志消息的Netlink套接字 |
netlink_xfrm_socket | 用于获取、管理和设置IPsec参数的Netlink套接字 |
netlink_selinux_socket | 用于接收策略载入通知,强制模式切换和清空AVC缓存的Netlink套接字 |
netlink_audit_socket | 用于控制审核的Netlink套接字 |
netlink_ip6fw_socket | 用于创建用户空间IPV6防火墙过滤器的Netlink套接字 |
netlink_dnrt_socket | 用于控制DECnet路由的Netlink套接字 |
association | IPsec安全关联 |
netlink_kobject_uevent_socket | 用于在用户空间接收内核事件通知的Netlink套接字 |
appletalk_socket | |
packet | |
dccp_socket | |
tun_socket |
客体类别 | 描述 |
---|---|
sem | 信号量 |
msg | 消息队列中的消息 |
msgq | 消息队列 |
shm | 共享内存段 |
ipc | 已经没有使用了 |
客体类别 | 描述 |
---|---|
security | 内核中的SELinux安全服务器 |
process | SELinux中的进程 |
system | 整个系统 |
capability | Linux中表示权利的特权 |
key | |
memprotect | |
peer | |
capability2 | |
kernel_service |
file许可 | 描述 | 分类 |
---|---|---|
ioctl | ioctl(2)系统调用请求 | |
read | 读取文件内容,对应标准Linux下的r访问权 | 标准Linux许可 |
write | 写入文件内容,对应标准Linux下的w访问权 | 标准Linux许可 |
create | 创建一个新文件 | |
getattr | 获取文件的属性,如访问模式(例如:stat,部分ioctl) | |
setattr | 改变文件的属性,如访问模式(例如:chmod,部分ioctl) | |
lock | 设置和清除文件锁 | |
relabelfrom | 从现有类型改变安全上下文 | SELinux特定许可 |
relabelto | 改变新类型的安全上下文 | SELinux特定许可 |
append | 附加到文件内容(即用o_append标记打开) | 文件扩展许可 |
unlink | 移除硬链接(删除) | |
link | 创建一个硬链接 | |
rename | 重命名一个硬链接 | |
execute | 执行,与标准Linux下的x访问权一致 | 标准Linux许可 |
swapon | 不赞成使用。它用于将文件当做换页/交换空间 | 文件扩展许可 |
quotaon | 允许文件用作一个限额数据库 | 文件扩展许可 |
mounton | 用作挂载点 | 文件扩展许可 |
audit_access | ||
open | 打开文件 | |
execmod | 使被修改过的文件可执行(含有写时复制的意思) | SELinux特定许可 |
execute_no_trans | 在访问者域转换的执行文件(即没有域转换) | SELinux特定许可 |
entrypoint | 通过域转换,可以用作新域的入口点的文件,允许精确控制什么代码可以执行什么域类型 | SELinux特定许可 |
process许可 | 描述 | 分类 |
---|---|---|
fork | 派生两个进程 | 创建进程 |
transition | 通过execve(2)系统调用转换到一个新的上下文(域类型) | 进程域类型转换 |
sigchld | 发送sigchld信号 | 进程信号 |
sigkill | 发送sigkill信号 | 进程信号 |
sigstop | 发送sigstop信号 | 进程信号 |
signull | 不发送信号测试另一个进程的存在性 | 进程信号 |
signal | 发送一个非sigkill,sigstop或sigchld的信号 | 进程信号 |
ptrace | 跟踪程序执行的父进程或子进程 | |
getsched | 获取进程的优先级 | 进程属性 |
setsched | 设置进程的优先级 | 进程属性 |
getsession | 获取进程的会话ID | 进程属性 |
getpgid | 获取进程的组进程ID | 进程属性 |
setpgid | 设置进程的组进程ID | 进程属性 |
getcap | 获取这个进程允许的Linux能力 | 进程属性 |
setcap | 为进程设置允许的Linux能力 | 进程属性 |
share | 允许与克隆的或派生的进程共享状态 | 创建进程 |
getattr | 通过/proc/[pid]/attr/目录获取进程的属性 | |
setexec | 下一次调用execve(2)时覆盖默认的上下文 | |
setfscreate | 允许进程设置由其创建的客体的上下文 | |
noatsecure | 禁用清除安全模式环境,允许进程在execve(2)上禁用glibc的安全模式特性 | 进程域类型转换 |
siginh | 在execve(2)上继承信号状态 | 创建进程 |
setrlimit | 改变进程硬性资源限制 | |
rlimitinh | 在execve(2上)继承进程资源限制 | 创建进程 |
dyntransition | 允许进程动态地转移到新的上下文中 | 进程域类型转换 |
setcurrent | 设置当前的进程上下文,当进程试图执行一个动态域转换时,这是第一个检查的能力 | |
execmem | 产生一个匿名的映像或可写的私有文件映像可执行体 | 执行可写入内存 |
execstack | 产生进程堆栈可执行体 | 执行可写入内存 |
execheap | 产生一个堆栈可执行体 | 执行可写入内存 |
setkeycreate | ||
setsockcreate |
#移除与selinux冲突的安全组件apparmor sudo systemctl stop snapd.socket sudo systemctl stop snapd sudo apt purge snapd -y sudo systemctl stop apparmor sudo apt purge apparmor -y #如果需要使用自定义用户角色,则需要移除gdm3改用lightdm #否则登录时检测不到合法上下文,会黑屏 sudo apt purge gdm3 -y sudo apt install lightdm -y #安装selinux sudo apt install policycoreutils selinux-utils selinux-basics #可以使用 apt install --fix-broken 补充/更新依赖包 #检查/激活selinux sudo selinux-activate #设置selinux状态,建议初始设置为pemissive #config enforcing: sudo selinux-config-enforcing #config permissive: sed -i '/^SELINUX/{s/enforcing/permissive/;}' /etc/selinux/config #enforcing模式下可能导致系统无法启动,在grub界面选择advanced options for ubuntu - ubuntu with linux ***-generic (recovery mode) - 进入root,更改为pemissive模式重启登录后再分析avc日志即可 #获取selinux状态,会提示你重启计算机以启用selinux sestatus
文件不宜过大,如不能超过64M,许可不宜使用*
或~
包含过多的操作许可,否则semodule
时会报错:
Failed to resolve ?? statement at /var/lib/selinux/default/tmp/modules/400/??/cil:num
#此类错误也可能是boolean规则阻止了一部分加载模块的te语句导致的
不要使用未require
引用的对象,不要require
引用对象后反而不使用,否则checkmodule
会报错
注意格式,宏声明在前,如module
声明,require
其次,require
中需要使用tab
,然后才是allow
等,不要漏掉分号
不能使用冲突的规则,可以将同一个规则在不同模块中重复加载,不可以在不同模块中反复声明role、type等对象
allow
语法中,self
、-
只能用于type类型,*
、~
只能用于许可;~
后必须紧接{}
,各通配符不能组合使用
checkmodule
和semodule_package
生成的新文件权限不足,需要chmod
进行修改,如:chmod 777 *.mod
如果遇到奇怪的始终Permission deny的问题,可以关注一下semanage boolean -l
或 getsebool -a
是否有布尔规则限制
在/etc/selinux/targeted/contexts/users/
文件夹下添加 selinux_user 为名的文件,或直接修改/etc/selinux/targeted/contexts/default_context
; 主要用于设置通过本地登录、ssh登录、su、sudo等方法登录SELinux用户时的安全上下文。其中/etc/selinux/targeted/contexts/failsafe_context
作为获取上下文失败的备用选项,文件内只有第一行有效,若均获取失败则以system_u:system_r:initrc_t
登录。
在/etc/selinux/targeted/contexts/default_type
文件下修改可直接设置selinux角色的默认类型,获取失败时将以unconfined_t
作为默认类型。
在/etc/sudoers
文件下修改或添加linux_user名的文件至/etc/sudoers.d/
下可直接设置sudo切换用户的默认上下文,获取失败时将以unconfined_r:unconfined_t
作为默认上下文。如: user_audit ALL=(ALL:ALL) TYPE=setype_audit ROLE=serole_audit ALL
,其中seuser按semanage login设置。
Private Policy File (.te) 私有策略文件 | External Interface File (.if) 外部接口文件 | File Labeling Policy File (.fc) 标记策略文件 |
---|---|---|
这个文件包括了模块专用的声明和规则,通常,所有模块类型和属性声明都包括在.te 文件中,以及授予这些类型和属性核心访问权的规则 | 这个文件包括模块接口,这些接口是其它模块访问这个模块的类型和属性,包含所有的其他守护进程和本守护进程通讯界面和本守护进程创建的文件类型 | 这个文件包括与这个模块有关的文件上下文标记语句,包含了文件和文件关联的映射 |
/sys/devices/system/cpu(/.*)? u:object_r:sysfs_devices_system_cpu:s0
/sys/power/wake_lock -- u:object_r:sysfs_wake_lock:s0
/sys/power/wake_unlock -- u:object_r:sysfs_wake_lock:s0
/sys/kernel/uevent_helper -- u:object_r:usermodehelper:s0
/sys/module/lowmemorykiller(/.*)? -- u:object_r:sysfs_lowmemorykiller:s0
/mnt/asec(/.*)? u:object_r:asec_apk_file:s0
/mnt/asec/[^/]+/[^/]+\.zip u:object_r:asec_public_file:s0
#支持正则表达式
#‘-b’ - Block Device ‘-c’ - Character Device
#‘-d’ - Directory ‘-p’ - Named Pipe
#‘-l’ - Symbolic Link ‘-s’ - Socket
#‘--’ - Ordinary file二进制文件
#te文件编译为pp文件
#Build the policy module
checkmodule -M -m -o myapp.mod myapp.te
#Build the policy package
semodule_package -o myapp.pp -m myapp.mod
#Load the policy package
semodule -i myapp.pp
#Remove the policy package
semodule -r myapp
#可以通过拷贝/usr/share/selinux/devel/Makefile到当前目录下make自动编译.te文件生成.pp策略包文件
#也可以直接使用audit2allow的-M选项
#测试时可以先再permissive模式下运行后,通过audit2allow命令分析/var/log/audit/audit.log: avc日志,构建其中所需的策略包(简单方便)
SELinux简介
SELinux策略语言–类型强制(编写TE规则)
安全利器 — SELinux
总结之策略规则&语法
默认客体类别和许可例举
深入理解SELinux SEAndroid
SEAndroid安全上下文关联分析
SELinux_FAQ
SELinux源码fork
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。