浅谈SEAndroid安全机制及应用方法

浅谈SEAndroid安全机制及应用方法

吐槽:准备学习一下SELinux/SEAndroid手里有一本书《深入理解Android内核设计思想》,看完章节“我是谁?我在哪?”能理解四层的意思,我发现另外的六层都是给会的人写的,头大难搞。趁着假期查资料看博客,一点一点修补本文章,有理解偏差或理解不到位的地方望大佬们纠正。
浅谈SEAndroid安全机制及应用方法_第1张图片
内容提纲:

➢SEAndroid/SELinux简介

➢SEAndroid/SELinux框架

➢SELinux Policy介绍

➢安全策略文件(TE文件)

➢SELinux安全问题分析

​ ----➢SELinux设备文件权限解决办法

​ ----➢SELinux服务权限解决办法

​ ----➢SELinux可执行权限解决办法

➢补充

​ ----➢客体类型添加

一.SEAndroid/SELinux简介

SELinux呢这里就不展开讲述了,直接进行SEAndroid机制。前段时间u盘插上板子,作者利用串口交互,以root用户想要删除U盘里的内容,就会报错误权限不足,这就得益于SEAndroid对设备的全面保护。
​ SEAndroid是Google在nlet 4.4 上正式推出的一套以SELinux为基础于核的系统安全机制。而SELinux则是由美国NSA (国安局)和一些公司( RedHat、Tresys )设计的一 个针对 的安全加强系统。NSA最初设计的安全模型叫FLASK ,全称为Flux Advanced Security Kernel (由Uta大学和美国国防部开发,后来由NSA将其开源) , 当时这套模型针对DTOS系统。后来, NSA觉得Linux更具发展和普及前景,所以就在Linux系统上重新实现了FLASK,称之为SELinux。

​ 两种安全机制DAC(Discretionary Access Control)和MAC(Mandatory Access Control)。通俗地讲,这两个机制的区别是。在DAC里,如果个应用获取了一个用户权限,如Root,那他的所有操作操作都是基于这个用户权限。而MAC就简单霸道好多,无论你是谁,甚至是有Root用户权限,文件权限为777,但每个动作都是需要被允许之后可以被执行。这里可以是在安全策略文件中被允许也可以是用户手动允许 。

二.SEAndroid/SELinux框架

浅谈SEAndroid安全机制及应用方法_第2张图片

用户看到的:服务权限、文件权限、属性权限、APP权限。

SELinux最终编译成libselinux.so文件,为上层提供服务。

三.SELinux Policy介绍

​ SELinux两个最基本的对象是主体( Subject )和客体(Object )。主体和客体分别对应的是"进程”和“文件”。这里的文件并不单指的是实际存在的文件,而是指Linux里"一 切皆文件”里指的文件。如Socket ,系统属性等。

​ 在SEAndroid中对主体和客体进行了进一步形式上的封装和扩展,其实差不多。SEAndroid里细分为 :系统文件,服务,系统属性,Binder和Socket.这里的系统属性指的是build.prop里的属性,也是getprop命令查询出来的属性。

浅谈SEAndroid安全机制及应用方法_第3张图片

1.ps - Z可以查看当前进程(主体)安全上下文。

root@rk3288:/ # ps -Z                                                          
LABEL                          USER      PID   PPID  NAME
u:r:init:s0                    root      1     0     /init
u:r:kernel:s0                  root      2     0     kthreadd
u:r:kernel:s0                  root      3     2     ksoftirqd/0
u:r:kernel:s0                  root      5     2     kworker/0:0H
u:r:kernel:s0                  root      7     2     migration/0
u:r:kernel:s0                  root      8     2     rcu_preempt
u:r:kernel:s0                  root      9     2     rcu_bh
u:r:kernel:s0                  root      10    2     rcu_sched
u:r:kernel:s0                  root      11    2     watchdog/0
u:r:kernel:s0                  root      12    2     watchdog/1
u:r:kernel:s0                  root      13    2     migration/1
u:r:kernel:s0                  root      14    2     ksoftirqd/1
u:r:kernel:s0                  root      16    2     kworker/1:0H
u:r:kernel:s0                  root      17    2     watchdog/2
u:r:kernel:s0                  root      18    2     migration/2
u:r:kernel:s0                  root      19    2     ksoftirqd/2
u:r:kernel:s0                  root      21    2     kworker/2:0H
u:r:kernel:s0                  root      22    2     watchdog/3
u:r:kernel:s0                  root      23    2     migration/3
u:r:kernel:s0                  root      24    2     ksoftirqd/3
u:r:kernel:s0                  root      26    2     kworker/3:0H
u:r:kernel:s0                  root      27    2     khelper
u:r:kernel:s0                  root      28    2     kdevtmpfs

左边的一列是Security Context。u:r:init:s0的意思是:

  • u,是指user,它代表SELinux的一个用户。

  • r,为role(角色)即Role Based Access(基于角色的访问控制,简称为RBAC),它是SELinux中比较高层次。简单点说,一个u可以属于多个role,不同的role具有不同的权限。

  • init/kernel,代表该进程所属的Domain(域)。

  • s0,SELinux为了满足军用和教育行业而设计的MultiLevel Security(MLS)机制。简单点说,MLS将系统的进程和文件进行了分级,不同级别的资源需要对应的级别的进程才能进行访问。

2.ls - Z可以查看当前文件(客体)安全上下文。

root@rk3288:/ # ls -Z                                                          
drwxr-xr-x root     root              u:object_r:cgroup:s0 acct
drwxrwxrwx root     root              u:object_r:rootfs:s0 bin
drwxrwx--- system   cache             u:object_r:cache_file:s0 cache
lrwxrwxrwx root     root              u:object_r:rootfs:s0 charger -> /sbin/healthd
dr-x------ root     root              u:object_r:rootfs:s0 config
lrwxrwxrwx root     root              u:object_r:rootfs:s0 d -> /sys/kernel/debug
drwxrwx--x system   system            u:object_r:system_data_file:s0 data
-rw-r--r-- root     root              u:object_r:rootfs:s0 default.prop
drwxr-xr-x root     root              u:object_r:device:s0 dev
drwx------ root     root              u:object_r:rootfs:s0 dmb
-rw-r--r-- root     root              u:object_r:rootfs:s0 drmboot.ko
drwxrwxrwx root     root              u:object_r:rootfs:s0 env_flag
lrwxrwxrwx root     root              u:object_r:rootfs:s0 etc -> /system/etc
-rw-r--r-- root     root              u:object_r:rootfs:s0 file_contexts
lrwxrwxrwx root     root              u:object_r:rootfs:s0 fstab.rk30board -> /fstab.rk30board.bootmode.emmc
-rw-r----- root     root              u:object_r:rootfs:s0 fstab.rk30board.bootmode.emmc
-rw-r----- root     root              u:object_r:rootfs:s0 fstab.rk30board.bootmode.unknown
drwxrwxrwx root     root              u:object_r:rootfs:s0 home
-rwxr-x--- root     root              u:object_r:init_exec:s0 init
-rwxr-x--- root     root              u:object_r:rootfs:s0 init.connectivity.rc
-rwxr-x--- root     root              u:object_r:rootfs:s0 init.environ.rc
-rwxr-x--- root     root              u:object_r:rootfs:s0 init.rc
-rw-r--r-- root     root              u:object_r:rootfs:s0 张志路-root.txt
  • u,是user的意思,表示创建这个文件的SELinux user。
  • object_r,这个标志位在文件里代表一个用户角色(role),不同的role具有不同的权限。
  • 这是一个type的标志位,也是TE里最重要的一个标志位。不然怎么怎么称为TE(Type Enforcement);它表示root目录对应的Type的rootfs。
  • s0,MLS的级别。

在这里细心的朋友就会注意到:“之前我们Linux的label不是UID/GID吗?怎么变成了user:role:type:security了呢?”没错这都是SEAndroid替换的,注意我说的是‘替换’。SEAndroid呢,主要通过label中的Type来定义安全策略的(这就是Type Enforment)这就是我们.te文件的由来。

读到这里你可能就要问了,上面分析的这些信息在哪里被设置定义的呢?这些信息都在xxx_contexts文件中被登记在案的,前提是要先type定义客体,这个下面还会讨论。
浅谈SEAndroid安全机制及应用方法_第4张图片

  • file_contexts
    即包括编译过程中文件的安全标签,也用于在运行时态对设备节点、socket端口、init.rc产生的/data目录进行安全标签的规划。当你创建新的安全策略时,在某些情况下需要更新这个文件夹分配新的标签。而为了让新标签生效,这里就要重新编译image或者执行restorecon命令。
  • genfs_contexts
  • 这个文件用于为不支持扩展属性的文件系统(列如proc和vfat)添加标签。这个配置将作为核心策略的一部分被加载。
  • property_contexts
    这个文件用于定制Android系统各属性的标签,以确认哪些进程可以设置他们。它将在系统启动时的init进程中被加载,或者是当selinux.reload_policy被置为1时被重新加载。
  • seapp_contexts
    这个文件用于为APP进程和/data/data文件夹指定标签。系统将在三个时机读取seapp_contexts文件:1.当一个APP被zygote进程孵化时;2.当installd在启动时;3.当selinux.reload_policy属性被置为1时。

四.安全策略文件(TE文件)

1.介绍

MAC的安全策略文件学名是TEAC(Type Enforcement Access Control)。简称TE。里面的语言被称为强制类型语言。

在Android源码中对应的TE文件所在的路径为Android源码/external/sepolicy/

浅谈SEAndroid安全机制及应用方法_第5张图片

2.语法

​ 在SELinux当中,所有访问都必须明确授权,SEL inx默认不允许任何访问,完全不考虑当前UG0结构,即不考虑用户/组ID是什么。这也就意味着,在这里没有超级用户了。那么如果主体需要对客体进行访问该如何进行呢?

在SELinux当中,通常是使用allow规则来指定主体类型(即域)对客体类型授子访问权限,也就是allow规则规定了哪些类型的进程可以访问哪些客体。allow规则由四部分组成:

/*     主体           客体            */
allow domains types:classes permissons
  • domains,原类型(Source type (s) )主体类型, 即域。用于单一进程或一系列进程。
  • types,目标类型(Target type(s)) 客体类型。用于标识客体(文件、Socket等)或一系列客体。
  • classes,客体类别(Object class (es) )客体的类别。被访问的客体(文件、Socket等)的具体种类。
  • permissons,许可(Permission (s) )主体可以对客体执行哪些操作(读、写等)我们称之为访问向量。

3.两种模式

SELinux Mode,SELinux Mode 有两种模式Permissve Mode(宽容模式)和Enforcing Mode(强制模式)。区别在于宽容模式只会打印SELinux Log。而强制模式会进行真正拦截。如果被拦截,kernel log中的关键字“avc:denied“。可以通过cat /sys/fs/selinux/enforc命令进行查看权限。

setenforce命令:

  • setenforce 0 关闭权限。
  • setenforce 1 打开权限。

五.SELinux安全问题分析

大致流程:

1.用type关键字定义客体。(这里就发挥一下我的联想类比能力。就好比出生去type一张身份证)

2.将定义的客体放到【file_contexts】或者【service_contexts】文件中,告诉系统你的客体。(就好像结婚登记)

3.用allow关键字添加说明主体访问客体的权限。(就好像修订自己家规家法)

log内容分析:

	avc:denied{
     connectto}  for  pid=2671  comm="ping"  
path="/dev/socket/dnsproxyd"
	scontext=u:r:shell:s0  tcontext=u:r:netd:s0   tclass=unix_stream_socket
  • {connectto},代表的是发生的行为。整个句子表示有人尝试去链接一个unix stream socket。
  • scontext,代表的是发生上述行为的主体的具体环境。在这个例子中就是某个以shell运行的程序。
  • tcontext,代表的是客体的具体环境。在这个例子中就是一个unix_stream_socket的所有者netd。
  • comm,comm="ping"表示的是当denial发生时究竟执行了什么语句。

1.SELinux设备文件权限解决办法

		[53692.570392] type=1400 audit(12565266.940:42): avc: denied 
		{
      read write } for pid=10794 comm="m.example.hello" name="led1" 
		dev="tmpfs" ino=39430 scontext=u:r:untrusted_app:s0 
		tcontext=u:object_r:device:s0 tclass=chr_file permissive=0

分析:

  • 缺少什么权限: read write
  • 谁缺少权限: scontext=u:r:untrusted_app:s0 untrusted_app
  • 对那个文件缺少权限:tcontext=u:object_r:device:s0 device
  • 什么类型的文件: tclass=chr_file chr_file

解决办法:在untrusted_app.te文件中添加

Allow untrusted_app device:chr_file {
     read write }

把缺少的权限添加上去,添加的过程如下:

先进去Android源码下的/external/sepolicy/下

①修改file_contexts
/dev/led1 u:object_r:led1_device:s0

②修改device.te
type led1_device, dev_type(, mlstrustedobject); (括号内为6.0权限)

③修改untrusted_app.te
allow untrusted_app led1_device:chr_file rw_file_perms;

添加好了之后重新编译Android的源码,烧写system.img和boot.img

2.SELinux服务权限解决办法

		131 E SELinux : avc:  denied  {
      add } for service=Hello 
		scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0
		tclass=service_manager

分析:

  • 缺少什么权限: { add }权限,
  • 谁缺少权限: system_server
  • 对哪个文件缺少权限:default_android_service
  • 什么类型的文件: tclass=service_manager

解决方法:在system_server.te中添加

allow system_server default_android_service:service_manager add;		

先进去Android源码下的/external/sepolicy/下

①在service.te文件中添加

​ type Hello_service, (app_api_service,)service_manager_type; (括号内为6.0权限)

②在service_contexts文件中添加
Hello u:object_r:Hello_service:s0

③在system_server.te文件中添加
allow system_server Hello_service: service_manager add;

3.SELinux可执行权限解决办法

			12-25 11:51:27.260   147   147 W init    : type=1400 
		audit(0.0:4): avc: denied {
     execute_no_trans } for 
		path="/system/bin/test" dev="nandd" ino=476 
		scontext=u:r:init:s0 tcontext=u:object_r:system_file:s0 
		tclass=file permissive=0

分析:

  • 缺少什么权限: execute_no_trans
  • 谁缺少权限: init
  • 对哪个文件缺少权限: system_file
  • 什么类型的文件: file

解决方法:在init.te中添加

allow init system_file:file execute_no_trans;

先进去Android源码下的/external/sepolicy/下

①新建test.te文件中添加

type test,domain;

type test_exec,exec_type,file_type;

init_daemon_domain(test)

②在file_contexts文件中添加
/system/bin/test u:object_r:test_exec:s0

③在init.te文件中添加
allow test system_file:file execute_no_trans;

添加好了之后重新编译Android的源码,烧写system.img和boot.img

六.补充

1.客体类型添加

​ 根据我们上面讲的TE文件语法那一小节,了解到allow语句。注意allow语句是主体访问客体缺少权限,allow语句添加权限信息。

但是系统并不认识我们写的客体,这时,我们就需要用type 语句定义一下我们的客体(客体类型添加),让系统认识一下。
这里我们先看一小段init.te的内容:
浅谈SEAndroid安全机制及应用方法_第6张图片
类型声明语法:

  • type 类型名称 [alias 别名集] [属性集],属性集:设备属性集dev_type,服务属性集service_manager_type;
  • 别名集如果有多个别名,可在一对大括号中用空
    格将各个别名区别开来,如: alias {aliasa_t aliasb_t}。
  • 属性集如果同时指定多个属性标识符,属性之间使用逗号进行分隔,如:bin_ type, file_ type, exec_ type;

2.在Android系统中定义自己的SEAndroid

Android系统是允许设备厂商定制自己的安全策略的。先留个尾巴,后续再写。

你可能感兴趣的:(Android)