淺談SEAndroid安全機制及應用方法

淺談SEAndroid安全機制及應用方法

吐槽:準備學習一下SELinux/SEAndroid手裏有一本書《深入理解Android內核設計思想》,看完章節“我是誰?我在哪?”能理解四層的意思,我發現另外的六層都是給會的人寫的,頭大難搞。趁着假期查資料看博客,一點一點修補本文章,有理解偏差或理解不到位的地方望大佬們糾正。
在這裏插入圖片描述
內容提綱:

➢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框架

在這裏插入圖片描述

用戶看到的:服務權限、文件權限、屬性權限、APP權限。

SELinux最終編譯成libselinux.so文件,爲上層提供服務。

三.SELinux Policy介紹

​ SELinux兩個最基本的對象是主體( Subject )和客體(Object )。主體和客體分別對應的是"進程”和“文件”。這裏的文件並不單指的是實際存在的文件,而是指Linux裏"一 切皆文件”裏指的文件。如Socket ,系統屬性等。

​ 在SEAndroid中對主體和客體進行了進一步形式上的封裝和擴展,其實差不多。SEAndroid裏細分爲 :系統文件,服務,系統屬性,Binder和Socket.這裏的系統屬性指的是build.prop裏的屬性,也是getprop命令查詢出來的屬性。

在這裏插入圖片描述

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定義客體,這個下面還會討論。
在這裏插入圖片描述

  • 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/

在這裏插入圖片描述

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的內容:
在這裏插入圖片描述
類型聲明語法:

  • type 類型名稱 [alias 別名集] [屬性集],屬性集:設備屬性集dev_type,服務屬性集service_manager_type;
  • 別名集如果有多個別名,可在一對大括號中用空
    格將各個別名區別開來,如: alias {aliasa_t aliasb_t}。
  • 屬性集如果同時指定多個屬性標識符,屬性之間使用逗號進行分隔,如:bin_ type, file_ type, exec_ type;

2.在Android系統中定義自己的SEAndroid

Android系統是允許設備廠商定製自己的安全策略的。先留個尾巴,後續再寫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章