Selinux-1

来源:互联网 发布:js中的深拷贝和浅拷贝 编辑:程序博客网 时间:2024/05/21 05:40
1. SELinux 来源
 SELinux 即Security-Enhanced Linux, 由美国国家安全局(NSA)发起, Secure Computing Corporation (SCC) 和 MITRE 直接参与开发, 以及很多研究机构(如犹他大学)一起参与的强制性安全审查机制, 该系统最初是作为一款通用访问软件,发布于 2000 年 12 月(代码采用 GPL 许可发布)。并在Linux Kernel 2.6 版本后, 有直接整合进入SELinux, 搭建在Linux Security Module(LSM)基础上, 目前已经成为最受欢迎,使用最广泛的安全方案.
 
2. SELinux 基本架构与原理.
 SELinux 是典型的MAC-Mandatory Access Controls 实现, 对系统中每个对象都生成一个安全上下文(Security Context), 每一个对象访问系统的资源都要进行安全上下文审查。审查的规则包括类型强制检测(type enforcement), 多层安全审查(Multi-Level Security), 以及基于角色的访问控制(RBAC: Role Based Access Control).

 SELinux 搭建在Linux Security Module(LSM)基础上, 关于 LSM 架构的详细描述请参见文章 “Linux Security Modules: General Security Support for the Linux Kernel”, 该文章在 2002 年的 USENIX Security 会议上发表。有完整的实现LSM 的所有hook function.
 SELinux 的整体结构如下图所示:

 
P-1-1-1: 整体流程图 

 SELinux 包含五个基本组成:
 * 用于处理文件系统的辅助模块, 即SELinuxFS.
 * 集成Linux Security Modules 的hooks sets.
 * Security Policy Database.
 * Security Label 验证模块.
 *  Access Vector Cache (AVC), 访问向量缓存,以便提高验证速度.
 
    基本的访问流程如下图所示:
 
 P-1-1-2: 访问流程图
 
 流程如下:
 * 进程通过系统调用(System Call) 访问某个资源, 进入Kernel 后, 先会做基本的检测, 如果异常则直接返回.
 * Linux Kernel DAC 审查, 如果异常则直接返回.
 * 调用Linux Kernel Modules 的相关hooks, 对接到SELinux 的hooks, 进而进行MAC 验证, 如果异常则直接返回.
 * 访问真正的系统资源.
 * 返回用户态, 将结构反馈.
 

2.SELinux and SEAndroid

1. SELinux and SEAndroid
   Android 是建立在标准的Linux Kernel 基础上, 自然也可以开启SELinux, 通常在通用移动平台上, 很少开启这样的安全服务, Google 为了进一步增强Android 的安全性, 经过长期的准备,目前已经在Android 5.0(L) 上有完整的开启SELinux, 并对SELinux 进行深入整合形成了SEAndroid.
  
2. SELinux 在Android 上的更新历史
 如下图所描述:
 
 
 P-1-2-1 SELinux 在Android 的更新过程
 * KK 4.4 针对netd, installd, zygote, vold 四个原本具有root 权限的process, 以及它们fork 出的子进程启用Enforce 模式.
 * L 版本普遍性开启SELinux Enforce mode.
 * Permissive 模式,只打印audit 异常LOG,不拒绝请求, Enforce 模式,即打印audit 异常LOG, 也拒绝请求
 
P-1-2-2 SELinux 在Android 启动模式变化
 估计后续版本Google 都会要求强制性开启SELinux, 以保证手机安全.
 
3. SELinux 给Android 带来的影响.
   * 严格限制了ROOT 权限, 以往ROOT “无法无天” 的情况将得到极大的改善.
   * 通过SELinux 保护, 降低系统关键进程受攻击的风险, 普通进程将没有权限直接连接到系统关键进程.
   * 进一步强化APP 的沙箱机制, 确保APP 难以做出异常行为或者攻击行为.
   * 将改变APP 一旦安装, 权限就已经顶死的历史, APP 权限动态调整将成为可能.

SELinux and SEAndroid
3.SELinux Mode

1. SELinux Mode.
   SELinux 分成两种模式, 即Permissve Mode(宽容模式), 和 Enfocing mode(强制模式).
   Permissive Mode 只通过Audit System 记录LOG, 但不真正拦截访问.
   Enforcing Mode 在打印LOG 的同时,还会真正的拦截访问.
   
   通常在调试时,我们会启用Permissive Mode, 以便尽可能的发现多的问题, 然后一次修正. 在真正量产时使用Enforcing mode, 来保护系统.

SELinux Basic Theory
4.DAC and MAC

1. DAC and MAC
 DAC 即 Discretionary Access control, 自主访问控制, 即系统只提供基本的验证, 完整的访问控制由开发者自己控制。
 MAC 即 Mandatory Access control, 强制性访问控制, 即系统针对每一项访问都进行严格的限制, 具体的限制策略由开发者给出.
 
2. Linux DAC
   Linux DAC 采用了一种非常简单的策略, 将资源访问者分成三类, 分别是Owner, Group, Other; 资源针对这三类访问者设置不同的访问权限. 而访问权限又分成 read, write, execute.
   访问者通常是进程有自己的uid/gid, 通过uid/gid 和 文件权限匹配, 来确定是否可以访问.
   将Root 权限根据不同的应用场景划分成许多的Root Capabilities, 其中如果有CAP_DAC_OVERRIDE 这项的话, 可以直接绕过Linux DAC 限制.
   
   Linux DAC 有明显的不足, 其中一个重要点就是, Root 权限 “无法无天”, 几乎可以做任意事情, 一旦入侵者拿到root 权限, 即已经完全掌控了系统. 另外每一个进程默认都拿到对应这个用户的所有权限, 可以改动/删除这个用户的所有文件资源, 明显这个难以防止恶意软件.
   
3. Linux MAC
   Linux MAC 针对DAC 的不足, 要求系统对每一项访问, 每访问一个文件资源都需要进行针对性的验证. 而这个针对性的验证是根据已经定义好了的策略进行. 在Linux Kernel, 所有的MAC 机制都是搭建在Linux Security Modules (LSM) 基础上, 包括有: SELinux、Apparmor、Smack 和 TOMOYO Linux等。目前SELinux 已经成了事实上的行业标准.
   
   针对Linux DAC, MAC 可以明显弥补DAC 的缺陷, 一方面限制Root 权限, 即使你有root 权限, 如果无法通过MAC 验证, 那么一样的无法真正执行相关的操作. 另外对每一项权限进行了更加完整的细化, 可限制用户对资源的访问行为.
5.Core SELinux Components and Security Context

1. Core SELinux Components
 SELinux 的核心组件可以参考下面的图:
 

 P-2-1-1 SELinux 核心组件
 * Subject 通常是指触发访问行为的对象, 在Linux 里面通常是一个进程(Process).
 * Object Manager 即是对象访问管理器, 即可以知道Subject 需要访问哪些资源,并且触发验证机制
 * Security Server 即安全服务器, 用来验证某个Subject 是否可以真正的访问某个Object, 而这个验证机制是基于定义好的Security Policy.
 * Security Policy 是一种描述SELinux Policy 的语言.
    * Access Vector Cache (AVC) 是访问缓存, 用来记录以往的访问验证情况, 以便提供效率,快速处理.
 
2. Security Context
 SELinux 给Linux 的所有对象都分配一个安全上下文(Security Context), 描述成一个标准的字符串。
 
 两种类型
 * Subject 主体, linux通常以进程为单位
 * Object  访问对象, linux 通常以文件为单位
 标准格式
 user:role:type[:range]
 * User: 用户, 非Linux UID。
 * Role:  角色,一个user可以属于多个role,不同的role具有不同的权限。它是SELinux中一种比较高层次,更方便的权限管理思路,即Role Based Access Control(基于角色的访问控制,简称为RBAC, SELinux 不推荐使用)。
    * Type: Subject或者Object的类型。 MAC的基础管理思路其实不是针对上面的RBAC,而是所谓的Type Enforcement Access Control(简称TEAC,一般用TE表示)。对进程来说,Type就是Domain。
    * Range: Multi-Level Security(MLS)的级别。MLS将系统的进程和文件进行了分级,不同级别的资源需要对应级别的进程才能访问。
 

 P-2-2-2 对象类型和权限项关系.
 每一个对象都有一个Class, 比如一支文件, 它是File Class 类型, 每个Class 类型都会根据实际情况定义权限类型项, 如: read, write, exec, ioctl, append 等等.
 
 Subject 即前面提到的主体,它能够产生访问行为, Linux 里面通常是一个process, 但process 本身也可能是一个Object, 比如另外一个进程对它发送Signal, 比如去对它进行Ptrace 操作.
 
3. 查看Security Context
 * 查看进程的Security Context 用: ps -Z 或者cat proc/PID/attr/current, 查看当前进程可用id, 如:
 
 
 P-2-2-3 ps 查询进程Security Context
 
 
* 查看文件的Security Context 用: ls -Z
 
P-2-2-4 查看文件Security Context

6.Type Enforcement Access Control

1. SELinux supports two forms of MAC
 * Type Enforcement (TE)
 顾名思义, Type Enforcement 是根据Security Label 中的 type 进行权限审查, 审查 subject type 对 object type 的某个class 类型中某种permission 是否具有访问权限,是目前使用最为广泛的MAC 审查机制, 简单易用。
 
 * Multi-Level Security (MLS)
 多层安全机制, 是基于Bell-La Padula (BLP) 模型, 将Subject 和 Object 定义成多层次的安全等级, 不同安全等级之间有相关的访问约束, 常见的访问约束是 "no write down" 和 "no read up". 它是根据Security Label 里面的最后一个字段label 进行确认的.
 
 目前在Android 中,重点启用了Type Enforcement 机制, Multi-Level Security (MLS) 虽然有定义, 但没有真实的投入使用, 这里暂时略过。
 
2. Type Enforcement Access Control
 
* 控制语句格式
   rule_name  source_type  target_type : class perm_set
 * rule:  控制类型, 分成两方面 allow 以及 audit
 * source_type:也叫subject,通常是domain。
 * Target_type:  代表请求的资源的类型
 * class perm_set: 代表对资源访问的操作
 
3. Rule of Type Enforcement
 如下表所示:
 
 
 P-2-3-1 TEAC-Rule
 
   * allow:赋予某项权限。
   * auditallow:audit含义就是记录某项操作。默认SELinux只记录那些权限检查失败的操作。  auditallow则使得权限检查成功的操作也被记录。注意,allowaudit只是允许记录,它和赋予权限没关系。赋予权限必须且只能使用allow语句。
    * dontaudit:对那些权限检查失败的操作不做记录。
    * neverallow:前面讲过,用来检查安全策略文件中是否有违反该项规则的allow语句
 
4. 简单的案例
   下面一段是截取的init.te 中的一部分
 # Create /data/property and files within it.
 allow init property_data_file:dir create_dir_perms;
 allow init property_data_file:file create_file_perms;
 
 # Set any property.
 allow init property_type:property_service set;
 
 # Run "ifup lo" to bring up the localhost interface
 allow init self:udp_socket { create ioctl };
 
 # This line seems suspect, as it should not really need to
 # set scheduling parameters for a kernel domain task.
 allow init kernel:process setsched;
 
 # The init domain is only entered via setcon from the kernel domain,
 # never via an exec-based transition.
 neverallow { domain -kernel} init:process dyntransition;
 neverallow domain init:process transition;
 neverallow init { file_type fs_type }:file entrypoint;

7.Domain and Object Transitions

1. Domain Transitions
 在SELinux 中, 我们通常称一个进程是一个domain, 一个进程fork 另外一个进程并执行(exec) 一个执行档时, 我们往往会涉及到domain 的切换. 比如init 进程, SELinux 给予了它很大的权限, 而它拉起的服务, 我们要限制这个服务的权限,于是就涉及到从一个domain 切换到另外一个domain, 不然默认就使用init 进程的domain.

 在SELinux 里面有专门的一条语法:
  type_transition statement.
 在准备切换前我们先要确保有相关的权限操作.
 *. The source domain has permission to transition into the target domain.
  源domain 必须有权限切换到这个目标domain.
 *. The application binary file needs to be executable in the source domain.
     源doamin 必须要有执行这个执行档的权限.
 *. The application binary file needs an entry point into the target domain.
  这个执行档必须是目标domain 的入口(Entry Point)
 
 如下面的demo, init 拉起apache 并且切换到 apache 的domain.
 #首先,你得让init_t域中的进程能够执行type为apache_exec_t的文件
 allow init_t apache_exec_t : file {read getattr execute};
 
 #然后,你还得告诉SELinux,允许init_t做DT切换以进入apache_t域
 allow init_t apache_t : process transition;
 
 #最后,你还得告诉SELinux,切换入口(对应为entrypoint权限)为执行apache_exec_t类型 的文件
 allow apache_t apache_exec_t : file entrypoint;
 
 #Domain Transition
 type_transition init_t apache_exec_t : process apache_t;
 
2. Object Transitions
 一个进程创建在一个目录下创建文件时, 默认是沿用父目录的Security Context, 如果要设置成特定的Label, 就必须进行Object Transitions.
 同样是使用
 type_transition statement.
 
 对应的必须有两个前提条件:
 * The source domain needs permission to add file entries into the directory
  这个process 必须有在这个目录下添加文件的权限.
 
 * The source domain needs permission to create file entries
  这个process 必须有在这个目录下创建以这个Security Context 为Label 的文件权限.
  
 下面是一个demo, ext_gateway_t 这个domain 在类型为in_queue_t 的目录下,创建类型为 in_file_t 的文件.
  
 #首先,你得让ext_gateway_t 对in_queue_t 目录具备访问权限
 allow ext_gateway_t in_queue_t : dir { write search add_name };
 
 #然后,你还得告诉SELinux,允许ext_gateway_t  访问in_file_t的文件
 allow ext_gateway_t in_file_t : file { write create getattr };
 
 #Object Transition
 type_transition ext_gateway_t in_queue_t : file in_file_t;
 
 结果如下图:
 
 
 P-2-4-1 对象domain 切换结果

Domain and Object Transitions
8.SEAndroid API

1. SELinux File System.
 SELinux 在Kernel 中实现, 统一对外的接口都集中在SELinux File System 当中, 即通过读写相关文件的方式来达成。
 SELinux File System 在比较新的Linux Kernel 中被mount 在/sys/fs/selinux. 老的版本就直接是/selinuxfs
 具体每一只文件的说明, 请参考:
 The SELinux Notebook: 2.19.2.3 SELinux Filesystem
 
2. SELinux Lib
 所有SELinux Lib 几乎都是对selinuxfs 的封装, 具体的API 可以参考:
 The SELinux Notebook: 9. APPENDIX B - LIBSELINUX LIBRARY FUNCTIONS
 
 在android 上, Google 有进一步对这些API 进行封装, 具体都在/external/libselinux 下面, 下面对一些重要的API 进行说明. (参考: http://selinuxproject.org/page/NB_SEforAndroid_1)
     selinux_android_setcontext
        Sets the correct domain context when launching applications using setcon(3). Information contained in the seapp_contexts file is used to compute the correct context.
        It is called by frameworks/base/core/jni/com_android_internal_os_Zygote.cpp when forking a new process and the system/core/run-as/run-as.c utility.
 
    selinux_android_setfilecon
        Sets the correct context on application directory / files using setfilecon(3). Information contained in the seapp_contexts file is used to compute the correct context.
        The function is used by the package installer within frameworks/native/cmds/installd/commands.c via the package install() and make_user_data() functions.
9.selinux commands
0 0