SELinux学习总结 (Ubuntu)

SELinux学习总结 - 目录

  • 一. 介绍
      • 1. 简介
      • 2. 作用
      • 3. [架构](https://blog.csdn.net/MyArrow/article/details/10063581)
  • 二. 英文缩写
  • 三. SELinux元素介绍
      • 1. 主体 (Subject)
      • 2. 客体 (Object)
      • 3. 策略和规则 (Policy & Rule)
      • 4. 安全上下文 (Security Context)
      • 5. SELinux工作模式
      • 6. 关于AVC拒绝日志
      • 7. 相关内核参数
  • 四. SELinux策略与规则命令
      • sestatus 命令 – 查询SELinux状态
      • seinfo 命令 – 查询SELinux策略规则
      • sesearch命令 - 搜索SELinux安全策略规则集
      • semanage - 管理SELinux安全策略
      • setsebool & getsebool - 管理SELinux布尔规则
      • chcon - 修改SELinux对象的安全上下文
      • restorecon - 恢复SELinux对象的安全上下文
      • auditctl - 控制SELinux审计系统状态/规则
      • ausearch - 搜索SELinux审计记录
      • aureport - 生成SELinux系统审计日志摘要
      • autrace- 生成SELinux进程跟踪报告
      • audit2why - 分析auditd日志文件avc拒绝原因
      • audit2allow - 提供auditd日志文件avc拒绝的建议规划
      • sealert - 分析日志文件
      • semodule - 管理SELinux策略模块
      • checkmodule - 检查/编译SELinux策略模块
      • semodule_package - 创建SELinux策略模块包
      • newrole - 切换SELinux角色 (in shell)
      • getseuser & getconlist - 获取SELinux用户有效上下文
  • 五. TE策略语言
      • 注释
      • 宏定义
      • 引入外部变量
      • type 声明类型
      • attribute 声明属性
      • typeattribute 指定属性
      • typealias 声明别名
      • 制定AV规则、audit规则
      • 制定type转换规则
      • class 声明客体类别(Object Class)
      • common 声明通用许可(PermSet)
      • role 声明角色
      • role_transition 制定角色规则
      • dominance 继承创建角色
      • 通配符以及特殊操作符
      • 定义系统安全上下文默认值
      • 自定义策略文件默认宏
  • 六. 默认客体类别和许可
    • 1.客体类别
        • ① 文件相关的客体类别
        • ② 网络相关的客体类别
        • ③ System V IPC客体类别
        • ④ 其他杂项客体类别
    • 2.许可
        • ① 文件客体类别相关许可
        • ② 进程客体类别相关许可
  • 七. Ubuntu使用SELinux心得
      • 安装与使用
      • te策略语言注意
      • 设置默认的 selinux user 上下文文件
      • 设置 selinux role 的默认type类型
      • 设置 sudo 的默认上下文
  • 八. 其他
      • 策略文件后缀与介绍
      • .fc等类型文件介绍
      • 策略包/模块的编译、安装示例
  • 九. 参考文章

一. 介绍

1. 简介

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 是一个标签系统,这意味着每个进程都有一个标签。每个文件、目录、以及系统对象都有一个标签。策略规则负责控制标签化的进程和标签化的对象之间的访问。由内核强制执行这些规则。

2. 作用

SELinux 主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则)。

在没有使用 SELinux 的操作系统中,决定一个资源是否能被访问的因素是:某个资源是否拥有对应用户的权限(读、写、执行)。只要访问这个资源的进程符合以上的条件就可以被访问。进程理论上所拥有的权限与执行它的用户的权限相同。比如,以root用户启动Browser,那么Browser就有root用户的权限,在Linux系统上能干任何事情。root 用户不受任何管制,系统上任何资源都可以无限制地访问。

在使用了 SELinux 的操作系统中,决定一个资源是否能被访问的因素除了上述因素之外,还需要判断每一类进程是否拥有对某一类资源的访问权限。

这样一来,即使进程是以 root 身份运行的,也需要判断这个进程的类型以及允许访问的资源类型才能决定是否允许访问某个资源,从而只能访问到它所需要的资源。进程的活动空间也可以被压缩到最小。

MAC 机制下,管理员定义好安全策略,用户行为被强制约束,避免发生意外。即使程序出了漏洞、系统受到攻击、进程和用户的权限被剥夺、用户账户泄露等情况下,影响范围也只有在其允许访问的资源范围内,安全性大大增加。

SELinux学习总结 (Ubuntu)_第1张图片

可以看到,在 DAC 模式下,只要相应目录有相应用户的权限,就可以被访问。而在 MAC 模式下,还要受进程允许访问目录范围的限制。

3. 架构

SELinux是通过LSM框架合并到内核中的

1.1 LSM框架
LSM框架的思想是允许安全模块以插件形式进入内核,以便更严格地控制Linux默认的基于身份的任意访问控制(DAC)安全性。LSM在内核系统调用逻辑中提供了一套钩子(hooks),这些钩子通常放在标准Linux访问检查后、且内核调用访问真实资源之前,下图举例说明了LSM框架的基础。

SELinux学习总结 (Ubuntu)_第2张图片

SELinux作为一个LSM模块载入内核,在访问被允许之前进行额外的访问确认。LSM框架的一个分支是只有当标准Linux访问(DAC)检查成功后SELinux才会生效。

1.2 SELinux LSM模块
SELinux LSM模块架构如下图所示:

SELinux学习总结 (Ubuntu)_第3张图片

客体管理器负责对它们管理的资源集强制执行安全服务器的策略决定,对于内核,你可以认为客体管理器是一个内核子系统,它创建并管理内核级客体。内核客体管理器的实例包括文件系统、进程管理和System V进程间通信(IPC)。在LSM架构中,客体管理器是通过LSM钩子描绘的,这些钩子分散在内核子系统各个地方,调用SELinux LSM模块做出访问决定。然后,LSM钩子通过允许或拒绝对内核资源的访问强制执行这些决定。

SELinux架构的第三方组件是访问向量缓存(AVC),AVC缓存是安全服务器为后面的访问检查准备的,目的是为了提升访问确认的速度。AVC还为LSM钩子和内核客体管理器提供了SELinux接口。

二. 英文缩写

  • SELinux (Security-Enhanced Linux) : 安全增强型Linux子系统
  • MAC (Mandatory Access Control) : 强制访问控制
  • DAC (Discretionary Access Control) : 自主访问控制
  • RBAC (Role Based Access Control) : 基于角色的访问控制
  • TEAC (Type Enforcement Accesc Control) : 类型强制的访问控制
  • TE (Type Enforcement) : 类型增强
  • AVC (Access Vector Cache) : 访问向量缓存
  • Subject : 主体
  • Object : 客体
  • Policy : 策略
  • Rule : 规则
  • Context : 上下文
  • Class : 类别,如:file、process
  • PermSet : 许可(集),同perm/perms/permission/P,表示主体对客体访问时允许的操作(OPT,operation),如:read、write
  • Attribute : 属性
  • Level : 安全等级
  • Category : 安全分类/安全类别
  • ST : source type,源类型,主体或者域的类型
  • TT : target type,目标类型,客体的类型
  • TT动作 : type transition,类型转换/客体转换动作
  • DT动作 : domain trasition,目标类型,域转换动作
  • MLS : Multi-Level Security,多级安全保护,是一个SELinux增强策略
  • MCS : Multi-Category Security,多类安全,是一个增强的SELinux,允许用户使用类别来标记文件

三. SELinux元素介绍

Linux中一切皆文件,而操作文件的为进程。进程能发起动作,例如它能打开文件并操作它。而文件只能被进程操作。我们这里可以看做主体对客体进行某种动作。

1. 主体 (Subject)

主体就是想要访问资源目标的源头。想要得到资源,基本流程是这样的:由用户调用命令,由命令产生进程,由进程去访问文件或目录资源。在自主访问控制系统中(Linux 默认权限中),靠权限控制的主体是用户;而在MAC系统中(SELinux 中),靠策略规则控制的主体则是进程。

2. 客体 (Object)

被主体访问的资源对象,也称为客体。可以是文件、目录、端口、设备等。

3. 策略和规则 (Policy & Rule)

对于 SELinux 来说,所选择的策略类型直接决定了使用哪种策略规则来执行主体(进程)可以访问的目标(文件或目录资源)。不仅如此,策略类型还决定需要哪些特定的安全上下文属性。通过策略类型,读者可以更精确地了解 SELinux 所实现的访问控制。

SELinux 提供 3 种不同的策略可供选择,分别是 Targeted、MLS 以及 MiNimum。每个策略分别实现了可满足不同需求的访问控制,因此,为了正确地选择一个满足特定安全需求的策略,就不得不先了解这些策略类型。

  • Target 策略

Target 策略即目标策略主要对系统中的服务进程进程访问控制,同时,它还可以限制其他进程和用户。服务进程都被放入沙盒,在此环境中,服务进程会被严格限制,以便使通过此类进程所引发的恶意攻击不会影响到其他服务或 Linux 系统。RBAC是基于TE的,而TE也是SELinux中最主要的部分。 type 是此策略下访问决定的主要组成部分。

沙盒(sandbox)是一种环境,在此环境中的进程可以运行,但对其他进程或资源的访问会被严格控制。换句话说,位于沙盒中的各个进程,都只是运行在自己的域(进程所运行的区域被称为“域”)内,它们无法访问其他进程或资源(除非被授予特殊的权限)。

通过使用此策略,可以更加安全地共享打印服务器、文件服务器、Web 服务器或其他服务,同时降低因访问这些服务而对系统中其他资源造成不利影响的风险。

  • MLS 策略:

多级安全保护策略,MLS,是 Multi-Level Security 的缩写,该策略会对系统中的所有进程进行控制。启用 MLS 之后,用户即便执行最简单的指令(如 ls)都会报错,这个策略限制得更为严格。

多级安全性方法背后的想法是 SELinux 支持敏感度级别(分层结构)和类别(没有分层相关性)。

敏感度级别是多级安全方法的分层部分。它通常通过公共、内部*、*机密和法规的数据分类敏感性来举例说明,尽管这完全可由管理员配置。使用敏感度标签,启用MLS的系统可以将某些内容标记为具有一定的灵敏度(或灵敏度范围,尽管通常资源使用单个敏感度标签进行标记),并将进程标记为支持灵敏度(或范围,在这种情况下,最高被视为“间隙”,而最低是“当前灵敏度”)。

使用敏感度标签,可以将某些资源(如文档)标记为机密,即使它们具有“标准”类型(如user_home_t)。如果用户只被允许公共和内部敏感级别,他将永远无法阅读此机密文档,即使

  1. 常规的 Linux 访问控制允许它
  2. SELinux 类型强制允许它
  3. 基于用户的访问控制约束允许它

多级安全性的第二部分是类别。类别可以看作是分配给资源的标签。类别的示例可以是部门名称(人力资源、基础设施、ICT、销售等)或项目(项目 1、项目 2 等),但也可以完全配置。与敏感度级别不同,类别彼此之间没有任何相关性。

类别的目的是进一步微调级别安全性。如果要授予用户进程对机密文档的访问权限,但只能授予两个部门的访问权限,则可以在机密:销售,ICT的敏感度级别中运行。标有不同类别的其他资源与此敏感度不兼容,因此被拒绝。

SELinux 的 MLS 部分将检查进程的上下文和目标资源的上下文,并查看它们之间的关系。这称为支配地位,有四种可能的回报:

  1. 进程的上下文主导资源上下文,这意味着资源的敏感度级别等于或低于进程的敏感度级别,并且进程的类别是超集(大于)或与目标资源相同。
  2. 流程上下文由资源上下文主导,这意味着资源的敏感度级别等于或高于进程的敏感度级别,并且流程的类别是与目标资源相同(小于)的子集。
  3. 流程的上下文和资源的上下文相同(相同的敏感度和类别)
  4. 流程的上下文和资源的上下文是无可比拟的:无论敏感度级别如何,每个上下文都至少有一个类别,而另一个上下文没有。

然后,MLS 策略指示在某些权限检查时会发生什么。例如,策略可能会说

  1. 仅当域主导资源的上下文时,才允许执行读取操作

  2. 仅当域由资源上下文主导时,才允许写入操作数

  • Minimum 策略

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)规则
  • 类型规则

我们使用AV规则允许或审核两个类型之间的访问权,在某些情况下使用类型规则控制默认的标记进行决定。

SELinux的一个重要概念是TE规则是将权限与程序的访问结合在一起,而不是结合用户。所有SELinux策略语言特性都是处理主体(正常的运行中的进程)对客体(文件、目录和套接字等)的访问权的,主要集中于程序访问控制决策,这也是SELinux的主要益处,它允许SELinux策略编写者基于程序的功能和安全属性,加上用户要完成任务需要的所有访问权做出访问决策,可以将程序限制到功能合适,权限最小化的程度,因此,即使它出了故障或被攻击破坏,但整个系统的安全并不会受到威胁。

SELinux是不会管用户的,可以给同一个程序指定多个域类型(因此有不同的特权集),这样就允许引入角色的概念,尽管如此,访问控制的标准仍然是基于程序的域类型而不是用户的特权。焦点是程序的访问权,而不是用户的访问权。selinux 的用户管理中,能跟踪一个登陆用户,即使用户通过 su 命令切换了身份,也被 selinux 视为同一个用户。

4. 安全上下文 (Security Context)

安全上下文是SELinux的核心,安全上下文即一种标签

安全上下文分为「进程安全上下文」和「文件安全上下文」

一个「进程安全上下文」一般对应多个「文件安全上下文」

进程安全上下文和文件安全上下文对应上,进程才能访问文件。它们的对应关系由策略中的规则决定。

文件安全上下文由文件创建的位置和创建文件的进程所决定,而且系统有一套默认值,用户也可以对默认值进行设定。

需要注意的是,单纯的移动文件操作并不会改变文件的安全上下文。

安全上下文是 SELinux 的核心,格式由多部分组成:用户、角色、类型标识符、安全等级、安全分类(方括号内为可选项):

格式 USER:ROLE:TYPE[:LEVEL[:CATEGORY]]
USER 用户 常见如:system_urootuser_u
ROLE 角色 常见如:staff_ruser_robject_rsecadm_rsysadm_rsystem_r
TYPE 类型/域 TEAC的重要属性,常见名称为**_t,系统资源|进程的type分别称为类型|域(domain)
LEVEL 安全等级 安全等级, 目前已经定义的安全等级为 s0 - s15,等级越来越高
CATEGORY 安全分类 分类,目前已经定义的分类为 c0 - c1023

其中LEVEL和CATEGORY仅在启用MLS后有效

很多系统命令,如 lspsid ,带有 -Z 参数,可以查看文件/进程的安全上下文。

pic

正如你从术语类型强制猜测的那样,类型是构成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 守护程序。在这种情况下,可能需要手动更改文件的安全上下文以确保它可以被访问。

5. SELinux工作模式

SELinux 有三种工作模式,分别是 enforcingpermissivedisabled

enforcing permissive disabled
强制模式 宽容模式 关闭SELinux安全策略
违反SELinux规则的行为都会被拦截阻止并记录到日志中 仅将违反SELinux规则的行为记录到日志中,不会拦截其行为 不拦截不记录

SELinux 工作模式可以通过 /etc/selinux/config 配置文件中 SELINUX 参数来配置,参考配置:

 SELINUX=enforcing | permissive | disabled

这里需要注意的是修改完配置需要重启系统才能生效。

当然,也可以通过 setenforce 1|0 来临时快速切换 enforcingpermissive,并通过 getenforce 或者 sestatus 命令来验证当前状态。

enforcing模式下SELinux的工作流程如图:

img

当主体想要访问目标客体时,如果系统中启动了 SELinux,则主体的访问请求首先需要和 SELinux 中定义好的策略规则进行匹配。如果进程符合策略中定义好的规则,则允许访问,这时进程的安全上下文就可以和目标的安全上下文进行匹配;如果比较失败,则拒绝访问,并通过 AVC(主要用于记录所有和 SELinux 相关的访问统计信息)生成拒绝访问信息。其中,Target策略下Type是安全过略唯一需要关注的字段。此后,如果安全上下文匹配,则可以正常访问目标文件。当然,最终是否可以真正地访问到目标文件,还要匹配产生进程(主体)的用户是否对目标文件拥有合理的读、写、执行(rwx)权限。

TE策略模型可以概述为:P = ST x OPT x TT:许可权限§ = 原类型(ST)对目标类型(TT)的资源类(class)的操作(OPT)

6. 关于AVC拒绝日志

当查看特定安全上下文的策略规则时,SELinux 会使用被称为 AVC(Access Vector Cache,访问矢量缓存)的缓存,如果访问被拒绝(也被称为 AVC 拒绝),则会在一个日志文件中记录下拒绝消息。

SELinux有大量的工具记录日志信息,或审核、访问尝试被策略允许或拒绝的信息。审核消息通常叫做"AVC消息",它提供了详细了关于访问尝试的信息,包括是允许还是拒绝,源和目标的安全上下文,以及其它一些访问尝试涉及到资源信息。AVC消息与其它内核消息类似,都是存储在/var/log目录下的日志文件中,它是策略开发、系统管理和系统监视不可缺少的工具。在此,我们检查是哪一个访问尝试产生了审核消息。

默认情况下,SELinux不会记录任何允许的访问检查,只会记录被拒绝的访问检查。这并没什么奇怪的,在大多数系统上,每秒会允许成千上万的访问,只有很少的一部分会被拒绝,允许的访问通常是在预料之中的,通常不需要审核,被拒绝的访问通常是(但不总是)非预期的访问,对它们进行审核便于管理员发现策略的bug和可能的入侵尝试。策略语言允许我们取消这些默认的预料之中的拒绝审核消息,改为记录允许的访问尝试审核消息。

这些被拒绝的消息可以帮助诊断和解决常规的 SELinux 策略违规行为,至于这些拒绝消息到底被记录在什么位置,则取决于 auditd 和 rsyslogd 守护进程的状态:

  • 若 auditd 守护进程正在运行,则拒绝消息将被记录与 /var/log/audit/audit.log 中。
  • 若 auditd 守护进程没有运行,但 rsyslogd 守护进程正在运行,则拒绝消息会记录到 /var/log/messages 中,或者 /var/log/syslog 中(如系统启动失败或者启动时异常等)。

注意,如果 auditd 和 rsyslogd 都在运行,那么拒绝消息将发送到 audit.log 和 messages 日志文件中。

通常使用 audit2whyaudit2allowsealert 命令来调试AVC拒绝日志。

  • SELinux AVC log 示例解读

整体翻译: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则操作放行。

7. 相关内核参数

在启动时改变 SELinux 模式的内核参数有:

autorelabel=1 → 强制给系统重新标签化
selinux=1 → 内核不加载 SELinux 基础设施的任何部分
enforcing=0 → 以许可permissive模式启动

四. SELinux策略与规则命令

sestatus 命令 – 查询SELinux状态

sestatus [参数]

参数: 
-v : 详细检查进程和文件的安全上下文
-b : 显示当前布尔值状态
  • 命令输出信息说明
    以下输出是在 ubuntu 20.04 上的 sestatus 命令:

    SELinux学习总结 (Ubuntu)_第4张图片

    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 命令 – 查询SELinux策略规则

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命令 - 搜索SELinux安全策略规则集

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 值在表达式中的条件规则

semanage - 管理SELinux安全策略

通用选项 含义
-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,不加载规则

setsebool & getsebool - 管理SELinux布尔规则

getsebool -a
getsebool rulename
获取某个或所有布尔规则的状态
setsebool [-P] rulename on/off
临时设定某个布尔规则的状态,打开或关闭
-P:permanent,永久设定(semanage boolean仅能临时设置)

chcon - 修改SELinux对象的安全上下文

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 - 恢复SELinux对象的安全上下文

restorecon [-iFnrRv] [-e excludedir ] [-o filename ] [-f filename | pathname...]

-i:忽略不存在的文件
-f:infilename 文件,infilename 中记录要处理的文件
-e:directory 排除目录
-R/-r:递归处理目录
-n:不改变文件标签
-o/outfilename:保存文件列表到 outfilename,在文件不正确情况下
-v:将过程显示到屏幕上
-F:强制恢复文件安全语境

auditctl - 控制SELinux审计系统状态/规则

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 - 搜索SELinux审计记录

  • 此命令必须以root用户执行
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 -ts <开始日期><开始时间>
-ua <所有用户UID> -o -su
-e <系统调用退出代码> -r (完全未格式化输出) -i (将数据格式转化为可读文本格式)

aureport - 生成SELinux系统审计日志摘要

  • 此命令必须以root用户执行
  • 此命令对/var/log/audit目录下的audit.log文件进行量化分析
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- 生成SELinux进程跟踪报告

  • 此命令必须以root用户执行
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 - 分析auditd日志文件avc拒绝原因

audit2why 命令用来分析 audit.log 日志文件,并分析 SELinux 为什么会拒绝进程的访问。也就是说,这个命令显示的都是 SELinux 的拒绝访问信息,而正确的信息会被忽略。命令的格式也非常简单

audit2why < 日志文件名 #通常直接使用/var/log/audit/audit.log

audit2allow - 提供auditd日志文件avc拒绝的建议规划

#输出的建议规划是以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 - 分析日志文件

sealert 命令是 setroubleshoot 客户端工具,也就是 SELinux 信息诊断客户端工具。虽然 setroubleshoot 服务已经不存在了,但是 sealert 命令还是可以使用的。

sealert [选项] 日志文件名
#选项: 
#-a: 分析指定的日志文件;

semodule - 管理SELinux策略模块

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策略模块

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 是用于从二进制策略模块和可选的其他数据(如文件上下文)创建 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 - 切换SELinux角色 (in shell)

newrole [-r|--role] ROLE [[-t|--type] TYPE] [[-l|--level] LEVEL]
#在当前bash等中切换当前user的其他角色

getseuser & getconlist - 获取SELinux用户有效上下文

getseuser linuxuser from_context
getconlist [-l level] selinux_user [context]

五. TE策略语言

注释

与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 声明类型

type 类型名称 [alias 别名集] [,属性集]
  1. 别名集:如果指定的不止一个别名标识符,要在一对大括号中用空格将各个别名区别开来,如:alias {aliasa_t aliasb_t}。
  2. 属性集:是一个或多个预先声明的属性标识符,如果同时指定多个属性标识符,属性之间使用逗号进行分隔,如:type bin_t, file_type, exec_type;
  3. 类型声明在整个策略中,以及基础载入模块和非基础载入模块中都是有效的。但在有条件的语句中无效。
  4. 从概念上将,赋予属性集的类型实质上已经改变了其类型的性质,因为它现在已经具有基于属性的访问许可了,而不只局限于类型本身了。
  5. 注意,关联执行后,将无法通过除了卸载相关策略模块或者修改te文件再重新加载策略模块以外的其他方式来取消关联。

attribute 声明属性

attribute 属性名称
  1. 属性和类型,别名都在同一个命名空间,因此不能与其他类型或别名重名。

  2. 属性声明在整个策略,基础载入模块和非基础载入模块中都有效,但在有条件的语句中无效。

  3. 一个类型可以有多个属性,一个属性可以囊括多个类型;在声明、关联一个属性时,会自动向具有此属性的类型组中所有类型进行声明、关联。

typeattribute 指定属性

typeattribute 类型名 属性名
  1. 一个或多个事先声明的属性标识符,如果指出多个属性标识符,属性标识符之间使用逗号分隔,如typeattribute bin_t file_type, exec_type;

  2. typeattribute语句在单个策略,基础载入模块和非基础载入模块中都是有效的,只有在条件语句中无效。

  3. typeattribute允许我们在一个地方type定义类型,在另一个地方再关联属性,增强了语言的灵活性。

typealias 声明别名

typealias 类型名称 alias 别名名称
  1. 类型名称:要添加别名的类型的名称,类型必须使用type语句单独声明,而且这里只能指定一个类型名称。

  2. 别名名称:如果同时指定多个别名,别名之间用空格分开,并使用大括号将所有别名括起来,如{aliasa_t aliasb_t}。

  3. typealias语句在单个策略,基础载入模块和非基础载入模块中都有效,只有在条件语句中无效。

制定AV规则、audit规则

命令名称 源类型集 目标类型集 : 客体类别集 操作许可集

命令名称

  • allow :表示允许主体对客体执行允许的操作(默认情况是不允许访问的)
  • dontaudit :表示不记录违反规则的决策信息,且违反规则不影响运行(允许操作且不记录)
  • auditallow :表示允许操作并记录访问决策信息(允许操作且记录)
  • neverallow :表示不允许主体对客体执行指定的操作

类型集

源类型集:授予访问的类型和(或)属性,通常是进程的域类型
目标类型集:客体的类型和(或)属性,源类型被授权可以访问的类型

按集使用时用空格进行分隔,并使用大括号将它们括起来,如{bin_t sbin_t}。

客体类别集

一个或多个客体类别(Object Class),多个客体类别必须使用大括号括起来,如{file lnk_file}。

操作许可集

表示主体对客体访问时允许的操作类型(也叫做访问向量),所有许可(PermSet)对类别集列出的所有客体类别都要有效。如{read execute create}。

制定type转换规则

类型规则在创建客体或在运行过程中重新标记时指定其默认类型,它仅提供一个新的默认类型标记

命令名称 源类型集 目标类型集 : 类别集 单个默认类型
  • type_transition :在转换过程中标记行为发生时以及创建客体时,指定默认转换、创建的类型

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 :使用SELinux的应用程序执行标记时指定其默认转换的类型,但不允许访问

我们可能很少使用type_change规则,因为它们通常只由核心操作系统服务使用。

class 声明客体类别(Object Class)

class 类别名 [inherits 通用许可集名] [{许可集}]

common 声明通用许可(PermSet)

common 通用名 {许可集}

声明许可有两种方法,第一种叫做通用许可(被多个客体类别所共用),它允许我们创建与客体类别一起作为一个组的许可,通用许可在类似的客体类别(如文件和符号连接)共享一套访问许可时很有用;第二种方法叫做特定类别许可(由某个客体类别所独用),它允许我们单独为客体类别声明特定的许可,通过class声明。正如将会看到的,有一些客体类别只有特定的许可,有一些只有通用许可,还有一些是这两者都有。

role 声明角色

role 角色名称 types [类型 类型集];
#仅role定义角色,当附带types类型时不为定义语句而作为关联语句使用(如typeattribute)

role_transition 制定角色规则

role_transition 角色集 类型集 目标角色

这个规则说明,当一个角色集的进程获取对应类型集的资源时,SELinux将会尝试将起转换为目标角色。

角色转换规则指定了执行一个文件时默认的角色变化,角色转换规则没有允许访问权,要成功转换角色,角色allow规则也是必须的:

allow 原角色 目标角色; 
#允许角色作转换

dominance 继承创建角色

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-*~ 通配符:

  1. 对于type — > 使用 - 来排除一个属性中的类型或属性中的类型,如 {exec_type -sbin_t};。其中还包含了一个特殊操作符 self : 使用语句中原类型的别名 self 作为目标类型即目标类型==源类型。在目标类型区域可以使用关键字 self ,但在源类型区域不能使用,如:allow domain self : process signal;
  2. 对于perm — > 可以使用通配符 * ,其包括了客体类别的所有许可;其次是求补算操作符 ~ ,即除了列出的许可外,其它的许可都包括。如: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):

1.客体类别

① 文件相关的客体类别
客体类别 描述
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
③ System V IPC客体类别
客体类别 描述
sem 信号量
msg 消息队列中的消息
msgq 消息队列
shm 共享内存段
ipc 已经没有使用了
④ 其他杂项客体类别
客体类别 描述
security 内核中的SELinux安全服务器
process SELinux中的进程
system 整个系统
capability Linux中表示权利的特权
key
memprotect
peer
capability2
kernel_service

2.许可

① 文件客体类别相关许可
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

七. Ubuntu使用SELinux心得

安装与使用

#移除与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

te策略语言注意

  1. 文件不宜过大,如不能超过64M,许可不宜使用*~包含过多的操作许可,否则semodule时会报错:

    Failed to resolve ?? statement at /var/lib/selinux/default/tmp/modules/400/??/cil:num
    #此类错误也可能是boolean规则阻止了一部分加载模块的te语句导致的
    
  2. 不要使用未require引用的对象,不要require引用对象后反而不使用,否则checkmodule会报错

  3. 注意格式,宏声明在前,如module声明,require其次,require中需要使用tab,然后才是allow等,不要漏掉分号

  4. 不能使用冲突的规则,可以将同一个规则在不同模块中重复加载,不可以在不同模块中反复声明role、type等对象

  5. allow语法中,self-只能用于type类型,*~只能用于许可;~后必须紧接{},各通配符不能组合使用

  6. checkmodulesemodule_package生成的新文件权限不足,需要chmod进行修改,如:chmod 777 *.mod

  7. 如果遇到奇怪的始终Permission deny的问题,可以关注一下semanage boolean -lgetsebool -a 是否有布尔规则限制

设置默认的 selinux user 上下文文件

/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登录。

设置 selinux role 的默认type类型

/etc/selinux/targeted/contexts/default_type文件下修改可直接设置selinux角色的默认类型,获取失败时将以unconfined_t作为默认类型。

设置 sudo 的默认上下文

/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 文件中,以及授予这些类型和属性核心访问权的规则 这个文件包括模块接口,这些接口是其它模块访问这个模块的类型和属性,包含所有的其他守护进程和本守护进程通讯界面和本守护进程创建的文件类型 这个文件包括与这个模块有关的文件上下文标记语句,包含了文件和文件关联的映射

.fc等类型文件介绍

/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

你可能感兴趣的:(学习,linux,ubuntu,android,后端)