Android系統app的domain(安全上下文)設定方法

背景

在運行了SELinux的Linux系統中,一般通過爲C/C++編寫的可執行文件指定特殊的安全上下文,然後用type_transition語句設定這些文件被執行後,產生對應的C/C++進程的安全上下文,通過這種方法,可以爲系統的所有C/C++進程設定我們需要的安全上下文。

在Android系統中,除了C/C++進程外,還有大量的java應用,上述的通過type_transition指定安全上下文的方法對於java應用不再適用,其設定安全上下文的方法要複雜一些,關係到apk本身的簽名證書,本文將講述如何設定Android O中java應用的安全上下文。

java app安全上下文的設定原理

apk的簽名

簽名的類型

Android上的apk都是經過簽名的,原生代碼中提供了4種key用於build階段爲應用進行簽名:

*Media
*Platform
*Shared
*Testkey

在Android源碼的build/target/product/security目錄下,存放着這四種類型對應的私鑰和x509格式的證書:
在這裏插入圖片描述

指定apk使用哪種簽名

在每個apk的Android.mk文件中,有一個LOCAL_CERTIFICATE字段,由它指定用哪個key簽名,如未通過這個字段進行指定,則默認用testkey。
在這裏插入圖片描述

指定apk的seinfo的值

在Android源碼的system/sepolicy/private/mac_permissions.xml文件中,可以根據apk的簽名類型,來指定apk的seinfo的值。以下圖爲例,當apk的簽名是Platform類型時,其對應的seinfo的值是platform。如果沒有指定簽名類型對應的seinfo的值,則seinfo的值默認使用default。
這個seinfo的值對apk的安全上下文的值十分重要,下面會詳細描述,我們先記住是在mac_permissions.xml這個文件通過signature的類型設定apk的seinfo值。
在這裏插入圖片描述

指定app的安全上下文

確定了apk的seinfo的值後,就可以在源碼的的system/sepolicy/private/seapp_contexts中指定app的安全上下文了。

以下圖第一行爲例,當應用的用戶是system,且seinfo的值爲platform,那麼這個app的安全上下文就是domain字段(Android系統一般將進程的安全上下文稱爲domain)的值system_app,而這個app對應的數據文件類型爲app_data_file,levelForm爲user(和多級安全相關,本文不做敘述。)

不難發現,在上面的例子中,滿足user爲system和seinfo爲platform的應用肯定不止一個,如果想將“精確定位”,只爲某個app指定安全上下文,可以在user和seinfo兩個條件以外,制定應用的名字,以圖中最後一條爲例,當user爲_app,seinfo爲media,且應用名字是android.process.media時,該應用的安全上下文爲mediaprovider。

從最後一條規則可以看出,如果app的各項信息和system/sepolicy/private/seapp_contexts的定義都無法完全符合,則默認使用untrusted_app_25作爲類型。
在這裏插入圖片描述

user字段的值

在system/sepolicy/private/seapp_contexts文件中,user字段表示應用屬於哪個user,Android系統實施了沙箱機制,每個應用都會分配給某個user,應用的uid即表示應用屬於哪個user,不同uid的應用默認無法訪問對方的數據。
Android系統保留了數字較小的用戶ID(1000~9999)專供系統使用,目前只有一部分被使用到了,定義在android_filesystem_config.h文件。
在這裏插入圖片描述
對於第三方的應用,如不適合使用系統預定義的uid,則會通過特定的算法,計算得到應用的uid,如下圖,通過ps可以看到應用的uid,格式爲ux_xxx,對於這類uid,在system/sepolicy/private/seapp_contexts文件中,需要將其user字段的值統一寫爲_app,否則規則將無法生效。
在這裏插入圖片描述
這類uid生成具體的算法參考下面的文章:
https://blog.csdn.net/keheinash/article/details/101100563
https://blog.csdn.net/keheinash/article/details/101100494

注意,上述的user並不是指登錄到系統的用戶,不要將這兩個概念混淆

疑問

有人可能會問,如果僅僅通過user和name兩個字段不就可以“鎖定”唯一的app嗎?爲什麼還需要加上seinfo來確認?
這種方法確實是可以確認唯一的應用,併爲該應用指定安全上下文,但是並不是對所有的應用有效。只有當user爲前面提到系統預留的uid時,纔可以忽略seinfo,如下圖,navigation是一個專供系統使用的保留uid,所以此規則可以通過編譯並且生效。
在這裏插入圖片描述

當user=_app時,SEAndroid的原生規則明確規定,seinfo字段不能爲空,這條規則在system/sepolicy/private/seapp_contexts文件中:
在這裏插入圖片描述
如下圖,如果user爲_app,去掉seinfo字段,當編譯SELinux的策略時,會直接報錯:
在這裏插入圖片描述在這裏插入圖片描述

已簽名app的安全上下文修改方法

嘗試指定安全上下文

如果第三方提供了一個用自己的密鑰簽過名的apk給我們,要如何指定其安全上下文呢?找一個符合這樣要求的apk,查看其Android.mk文件,發現LOCAL_CERTIFICATE的值爲:

LOCAL_CERTIFICATE := PRESIGNED

根據前面的方法,我們在自己開發維護的SELinux策略目錄中,增加mac_permissions.xml文件,在文件中指定,當signature值爲PRESIGNED時,seinfo的值爲presigned。
在這裏插入圖片描述
然後在自己的seapp_contexts文件指定app的安全上下文。
在這裏插入圖片描述
注意,上述的修改都是在自己的SELinux策略目錄中新增加的文件修改,不要修改/system/sepolicy下的內容,否則影響CTS認證。

完成上述修改後,編譯SELinux的策略,生成sepolicy、nonplat_mac_permissions.xml、nonplat_seapp_contexts等文件,都替換到機器上。但是通過ps -Z命令查看,發現應用並沒有按照我們的設想變成test_context類型,仍然是untrusted_app_25類型。

問題分析

首先懷疑我們的修改出了差錯,將進行了上述修改後編譯生成的nonplat_mac_permissions.xml、nonplat_seapp_contexts文件分別和原生代碼編譯生成的plat_mac_permissions.xml、plat_seapp_contexts文件進行,發現nonplat_mac_permissions.xml和plat_mac_permissions.xml文件的內容格式存在很大的差別,可以看到,plat_mac_permissions.xml文件存在大量的x509格式證書的內容:

原生策略文件system/sepolicy/private/mac_permissions.xml編譯生成的plat_mac_permissions.xml
我們自己的mac_permissions.xml文件編譯生成的nonplat_mac_permissions.xml文件
於是重新查看system/sepolicy/private/mac_permissions.xml,發現註釋說明裏有這麼一段描述,大概的意思是每個signer的tag都需要有一個對應的X509格式的證書,聯想到前面四種系統簽名都有對應x509.pem文件,於是先無腦猜測這個證書就是用於驗證apk簽名的證書
在這裏插入圖片描述
緊接着在源碼裏搜索包含keys.conf這個關鍵字的文件,確實存在這個文件
在這裏插入圖片描述
觀察文件的內容,發現對每個signature,都指定了存放對應x509格式證書的路徑,而且這個文件還能指定編譯不同版本(如USER或者USERDEBUG)分別使用不同的證書。
在這裏插入圖片描述
根據上面的分析,可以這樣猜測:在編譯SELinux的策略時,會去讀取源碼mac_permissions.xml的signature tag的值,然後在keys.conf查找對應的x509證書,將證書的內容寫入到編譯生成的plat_mac_permissions.xml和nonplat_mac_permissions.xml,只有證書可以成功驗證apk的簽名時,才允許將seinfo設置成你想要定義的值。

驗證

爲了驗證上面的猜測,我們用android.process.acore進行實驗。
android.process.acore使用shared類型進行簽名,於是我們在自己的mac_permissions.xml加上:
在這裏插入圖片描述
另外創建一個keys.conf文件,避免修改原生策略裏的文件,在keys.conf指定share類型證書的路徑:
在這裏插入圖片描述
最後在自己的seapp_contexts文件,將seinfo的值爲test_input_contexts,且app名字爲android.process.acore的應用的安全上下文指定爲input_t,當然input_t類型需要在策略裏預先定義,否則會編譯出錯
在這裏插入圖片描述

編譯策略,將需要替換的文件都替換到機器上,系統啓動後,通過ps -Z命令查看android.process.acore的安全上下文,已經轉換爲我們需要指定的安全上下文了:
在這裏插入圖片描述

總結

根據上面的分析和驗證,我們知道如果要修改已經簽名的app的安全上下文,需要指定其證書的路徑,同時在mac_permissions.xml文件指定seinfo的值,在seapp_contexts文件指定app的類型。

對於第三方提供的應用,如果是未經過簽名,可以根據我們的需要使用系統定義的四種類型的簽名,也可以使用我們自己的私鑰進行簽名,只要保證編譯策略的時候可以找得到signature類型對應的證書即可。

如果應用經過了第三方簽名,可以要求提供證書,或者將keystore文件轉換爲對應的pem證書。

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