selinux学习
一、基本概念
1、TE模型的安全上下文
所有的操作系統訪問控制都基于主體、客體,以及與他們相關的訪問控制屬性。
在selinux中,訪問控制屬性叫做安全上下文。所有對象(文件、進程間通信通道、套接字、網絡主機等)和主體(進程)都有一個與之關聯的安全上下文。
一個安全上下文包含三個元素:用戶(user)、角色(role)和類型標識符(type identifiers)
安全上下文的形式如下:user:role:type
對進程來說:分別表示用戶、角色、類型標識符也被稱為域
對客體來說:前兩項基本沒有實際用途,role通常為object_r,user通常位創建這個對象的進程的user,對訪問控制沒有影響
顯示安全上下文
加上-Z能顯示主體、客體的上下文
ls -Z能顯示文件系統的安全上下文
ps -Z能顯示進程的安全上下文
id -Z能顯示shell的安全上下文:joe:usr_r:usr_t
2、TE訪問控制
在SELinux中,默認時沒有允許規則的,也沒有超級用戶。被允許的訪問必須由規則給出。
一條規則如下:
allow Source type(s) Target type(s): Object class(es) Permission(s)
比如這樣的訪問規則:
allow user_t bin_t : file {read execute getattr};
表示允許域為user_t的進程對type為bin_t的文件具有讀、執行、得到屬性的操作
3、角色的作用
SELinux也提供基于角色的訪問控制
通過以下語句指定role的type:
role user_r type passwd_t;
如果沒有以上這條語句,則:
安全上下文joe:user_r:passwd_t則不能被創建
exec調用則失敗,即便策略允許
二、架構
1、內核架構
基于LSM(linux security module),為所有的內核的資源提供強制訪問控制
LSM提供了一系列的鉤子函數
如果訪問被DAC拒絕,則會影響審計結果
SELinux的架構如下所示:
策略決定包含在安全服務器中,與具體架構無關,便于移植
對象管理者時各對象的管理者,在LSM架構中,是一系列的LSM鉤子,遍布在內核的子系統中。
2、用戶空間的對象管理器
SELinux支持將對象管理器放到用戶態,使用內核的對象管理策略服務器來管理用戶態的對象
然而,支持用戶空間的對象管理器有一些弱點:
對于TE模型,還需要定義class
對于對象管理器的管理策略不再內核之中
策略服務架構如下:
AVC表示各種緩存
三、class
SELinux的客體除了有type,還有class,進一步對客體的類型進行劃分
SELinux中幾個常用的客體類別(class),及其權限
file:read、write、execute、getattr、create
dir:read、write、search、rmdir
process:signal、transition(域的轉換)、fork、getattr
socket:bind、listen、connect、accept
filesystem:mount、unmount
四、TE策略
在TE模型中,主體通常是正在運行的進程,而不是用戶。客體可以是文件、進程、socket等。
TE模型定義了一系列的規則來表示訪問是否允許,如果沒有規則,則所有的訪問都是不被允許的。
TE規則主要分為兩大類:access vector(AV)和type rules,AV允許審計,而type rules決定控制策略
1、類型(type)、屬性(attributes)、別名(aliases)
type:在selinux中,將對資源的訪問抽象為主體對客體的訪問,主體分為多個type,也叫做域,客體也分為多個type,每個type里還能更加細分出class,selinux的訪問規則就是基于type建立的規則,所以叫TE模型。
attributes:用來引用一組具有相同標識符的一組類型
alases:對于策略而言,別名標準符和類型標識符是一致的
一個type申明語句的格式如下,中括號中代表的是可選項:
type type_name [alias alias_set] [, attribute_set]
例子:typehttpd_user_content_t ,file_type
例子:
舉一個例子說明屬性的作用
假設現在新建了一個type為backup_t:
type backup_t;
需要對backup_t賦予所有文件的讀權限,如果系統中有shadow_t文件和httpd_user_content_t類型的文件,那么需要以下兩條的規則來賦予文件讀權限
allow backup_thttpd_user_content_t :file read
allowbackup_t shadow_t:file read
假設現在多了一個類型的文件,那么就需要重新為backup_t新增一條規則,這樣不僅麻煩而且錯誤率很高
現在有了一個屬性file_type
attribute file_type;
然后將所有具有file_type屬性的文件的讀權限賦予backup_t
allow backup_t file_type:file read;
這樣,以后每次有新的文件type出現,只需要將新文件的type域file_type屬性關聯起來就行,backup_t會自動獲得讀權限
以上的例子簡單說明了屬性的使用,一個type可以關聯到多個屬性,將type和attribute關聯起來可以使用typeattribute,格式為:
typeattribute type_name attrib_name
別名用來保證兼容性,使用typealias來關聯,格式如下:
typealias type_name alias alias_names;
2、AV(access rules)規則
AV規則有四類
allow:允許兩個類型之間的具體訪問
dontaudit:指定不記錄拒絕訪問的信息
auditallow:允許事件被記錄
neverallow:指定規則永遠不會被賦予訪問權限
alow規則
格式:
allow source_type target_type :objectclass{permission}
例子:
allow user_d bin_t : file{read、execute、getattr}
允許user_d域的進程對bin_t類型的普通文件進行讀、寫、取屬性操作
AV規則通用語法
所有的AV規則的語法都同于上述的allow規則
在AV規則中使用屬性
以allow的例子為例,定義了file_type的屬性之后,可以將規則寫為:
allow user_d file_type: file{read、execute、getattr}
如果定義了主體的的type,則規則可以寫為:
allow domain file_type: file{read、execute、getattr}
多個type和attribute
如果有多個type和attribute存在,則可以用括號表示多個,并且type的attribute可以混用
allow {domain user_t} {file_type bin_t}: file{read、execute、getattr}
self
規則中可以出現self字樣,以下兩條規則等價
allow user_t user_t : process signal;
allow user_tself: process signal;
類型否定
類型否定用來在一系列的type中減去某個type,比如以下規則從exec_type中減去sbin_t
allow domain (exec_type -sbin_t): file{read、execute、getattr}
class的權限
allow user_tbin_t: {file dir} {read getattr}
等價于:
allow user_tbin_t: file {read getattr}
allow user_tbin_t: dir {read getattr}
通配符
allow user_tbin_t: dir *
表示賦予所有權限
取反操作符
allow user_tbin_t: file ~{read getattr}
表示除了read和getattr之外的權限全部賦予
審計規則
默認情況下,允許的訪問時不被記錄的,而不允許的訪問會被記錄下,比如以下的兩個指令
dontaudit:指定不記錄拒絕訪問的信息
auditallow:允許事件被記錄
從不允許
neverallow:指定規則永遠不會被賦予訪問權限
3、策略規則
策略規則中有兩類
type_transition:
type_change:
通用規則語義
rule_name source_type target_type object_class defult_type
例子:
type_transition user_t passwd_exec_t : process passwd_t;
以上規則表示,當一個user_t域的進程執行類型為passwd_exec_t的文件時,進程的type默認轉移到passwd_t
注意:在以上的語法中,處了default_type不能使用集合,其他都能使用集合
type轉移
進程在fork的時候繼承父進程的type,而文件在在創建時繼承自容器的type,例如目錄
假設有如下規則:
type_transition user_t passwd_exec_t : process passwd_t;‘
在上述例子中,defult_type就是默認要轉移的type
但是需要完成一個完整的轉移不僅僅需要上述的一條規則,總共需要3條。’
例子:
type為init_t的進程fork一個子進程,然后執行type為appache_exec_t的文件,同時進程的域需要轉移到apache_t
一共需要3條規則
1、原域必須對目標類型有執行權限(init_t對appache_exec_t有執行權限)
2、原域必須對目標域有轉移權限(init_t對apache_t有轉移權限)
3、目標域必須對目標文件類型有entrypoint權限(apache_t對appache_exec_t有entrypoint權限)
object轉移
type_transition passwd_t tmp_t : file passwd_tmp_t;
以上例子表示當一個passwd_t進程在tmp_t 目錄下創建一個文件時,文件的類型為passwd_tmp_t
需要的規則包括
1、tmp_t的增加名字,寫,搜索權限
2、passwd_tmp_t的寫和創建權限
type改變,type_change
type改變時用來指明重新執行時的默認類型,像type_transition一樣,指明默認但是不允許,
type_change sysadm_t tty_device_t : chr_file sysadm_tty_device_t;
這個type_change規則聲明,當代表sysadm_t重新標記tty_device_t類型的字符文件時,應該使用sysadm_tty_device_t類型。
這個規則是type_change規則最常用的一個例子,即在用戶登錄時重新標記終端設備。
登錄程序將通過SELinux模塊的內核接口查詢策略,傳入類型sysadm_t和tty_device_t,并接收類型sysadm_tty_device_t作為用于relabel更改的類型。
這種機制允許登錄過程在新的登錄會話期間代表用戶對tty設備進行標記,同時將類型的細節封裝在策略中,而不是硬編碼在應用程序中。
五、用戶和角色
SELinux中的角色和用戶是其RBAC特性的基礎。大多數其他主流操作系統的安全特性主要集中于授予用戶訪問權限,或者直接授予用戶訪問權限,或者通過某種形式的組或角色機制授予用戶訪問權限。在SELinux中,通過TE allow規則將訪問權限授予類型。
角色充當類型強制的支持特性,并與用戶一起提供一種方法,將基于類型的訪問控制與Linux用戶及其允許運行的程序綁定在一起。SELinux中的RBAC通過定義域類型和用戶之間的關系來控制Linux用戶的特權和訪問權限,從而進一步限制了類型強制。
Linux和SELinux有不同的用戶標識符,有時是相關的。Linux用戶是指/etc/passwd中定義的用戶帳戶SELinux用戶是指安全上下文中在SELinux策略中定義的用戶標識符。
通過將域類型與一個或多個角色關聯,我們間接地向用戶授予特權。RBAC策略語句不授予訪問權限。相反,RBAC通過控制安全上下文中域類型、角色和用戶的關聯來進一步約束TE策略SELinux 沒有直接給“用戶”授權。SELinux的安全策略定義了一個用戶可以跟哪些角色關聯一個角色可以跟哪些域類型關聯
最終定義了一個用戶可以跟哪些域類型關聯,用戶關聯的域類型才可以執行該域類型的程序,才具有該域類型的權限。一個用戶要執行一個可執行程序時,會產生域切換;SELinux控制一個角色可以切換到哪些角色;SELinux控制角色與域類型的關聯進而控制角色可以可以運行的程序角色的切換和角色與域類型的關聯控制了用戶的權限。
域從域類型為user_t的bash shell進程轉換為運行域類型為passwd_t的密碼程序的進程。我們為流程安全上下文添加了用戶和角色部分的安全上下文joe: user_r: user_t joe: user_r: passwd_t
這個例子演示了兩種RBAC策略語句:一個用戶聲明語句(user)和兩個角色聲明語句(role)。用戶語句“user joe roles {user_r}”將SELinux用戶joe與角色user_r關聯起來。該語句告訴SELinux,允許用戶joe和角色user_r在安全上下文中共存。如果沒有這條語句,圖中的user joe和role user_r進程安全上下文將無效,SELinux將拒絕創建它們,從而拒絕域轉換嘗試。
這兩個角色語句將角色user_r與域類型user_t和passwd_t關聯起來。要使流程安全上下文有效,角色語句是必需的。如果沒有關聯類型passwd_t的role語句,即使TE策略允許,這個域轉換也會失敗。如果我們不希望user_r角色運行密碼程序,那么只需刪除這個角色語句,即使TE規則允許訪問,內核也永遠不會創建安全上下文。
1、role語句
除了object_r之外,SELinux沒有任何內置角色。與類型一樣,角色也是在策略中聲明的,并通過一致的使用賦予其意義。
role有四個相關聯的語句:
1、role聲明語句
2、role允許語句
3、role轉移語句
4、role支配語句
角色聲明語句
格式為:
role role_name [types type_set];
角色聲明語句聲明角色標識符并將類型與角色關聯起來。類型必須與角色關聯,以便與角色在安全上下文中共存。給定角色標識符的第一個角色語句除了關聯列出的類型外,還將聲明該角色。所有后續角色語句都關聯其他類型。單個角色的多個角色語句通常用于將角色語句放置在與其關聯的類型的聲明附近
角色允許語句
格式為:
allow role_set role_set;
SELinux提供了一種通過execve()系統調用在程序執行期間更改角色的方法。這個特性在本質上類似于域轉換,這會導致域類型的更改。角色允許規則(allow)通過指定允許哪些角色更改為其他角色來控制在程序執行時可能發生的角色更改。
角色轉移規則
因為角色可以在程序執行時以類似于類型的方式進行更改,所以我們需要一種方法在策略語言中自動完成這種轉換。對于類型,我們使用type_transition規則來指定自動的默認類型轉換。對于角色,我們有角色轉換規則(role_transition)。這個規則在目的和語法上與type_transition規則類似,只是它指定了在執行文件時發生的默認角色更改。
格式為:
role_transition role_set type_set role;
例子:
role_transition sysadm_r http_exec_t system_r;
此規則聲明,除非另有要求,否則當角色為sysadm_r的進程執行類型為http_exec_t的文件時,SELinux應該嘗試將角色更改為system_r。
角色支配語句
格式為:
dominance { role role_name { role_set} }
角色優勢語句指定角色之間的層次關系。角色繼承它們所控制的角色的所有類型關聯。
表單角色“role_name”中指定的一個或多個角色;使用空格分隔的列表指定多個角色(例如,{role staff_r;sysadm_r作用;})
例子:
dominance { role a_r { role b_r; role c_r { role d_r; } } }
d_r關聯的角色只有它自己的類型
c_r它的類型和d_r的類型
d_r關聯的角色只有它自己的類型
a_r它自己的類型以及b_r、c_r和d_r中的所有類型
2、用戶和用戶語句
Linux和SELinux用戶標識符是不同的,通常是不相關的。在SELinux中,Linux用戶標識符和給定進程的SELinux用戶標識符可能不同。SELinux使用不同的用戶標識符(而不是共享Linux的標識符)的設計決策的動機是希望創建不可變的SELinux用戶標識符。在標準Linux中,用戶標識符的變化反映權限的變化(例如,更改為root)。在許多情況下,實際的和有效的用戶標識符都會發生變化。這使得跟蹤哪個用戶登錄進行審計、身份驗證和其他使用變得困難。分離Linux和SELinux用戶標識符允許Linux用戶標識符在不影響SELinux的情況下根據需要進行更改。
user聲明語句(user)在策略中聲明一個用戶標識符,并將其與一個或多個角色關聯。user語句是與SELinux用戶相關的惟一策略語句。用戶語句必須在所有類型和角色語句之后以及約束之前
格式如下:
user user_name roles role_set;
假設有如下規則:
user joe roles { user_r };
如果策略中尚未聲明用戶joe,則該語句聲明該用戶joe,并將角色user_r與該用戶關聯起來。
將SELinux的用戶和linux用戶關聯
登錄程序(例如,login, sshd)負責將Linux用戶映射到SELinux用戶。登錄時,如果有一個與Linux用戶標識符完全相同的SELinux用戶標識符,則匹配的SELinux用戶標識符將成為初始shell進程的安全上下文中的用戶標識符。
在許多情況下,不希望在策略中定義每個普通用戶。對于SELinux(即user_r角色和user_t初始用戶域類型),普通用戶通常具有相同的特權。為了解決這個問題,SELinux有一個特殊的用戶標識user_u,稱為泛型用戶。如果策略中定義了通用用戶user_u,那么如果策略中沒有匹配的SELinux用戶,那么所有Linux用戶都將映射到它。
對于語句:
user user_u roles { user_r };
這個語句定義了通用用戶user_u,并將其授權給角色user_r,就像我們前面為joe所做的那樣。
如果在策略中定義user_u,則將策略中未顯式定義的所有Linux用戶映射到user_u。例如,如果jane是一個Linux用戶標識符,但是SELinux策略中沒有定義用戶jane,那么當Linux用戶jane登錄時,初始shell進程安全上下文中的用戶標識符將是user_u。因為joe是在策略中定義的,所以該用戶的初始SELinux用戶標識符將是joe,即使user_u也是在策略中定義的。
如果在策略中沒有定義泛型用戶user_u,那么在SELinux策略中沒有顯式定義的任何Linux用戶標識符都將無法登錄,即使在許可模式下也是如此。
登錄時,初始shell進程必須具有有效的安全上下文,包括用戶標識符。如果策略中既沒有定義user_u,也沒有定義Linux用戶標識符,則登錄過程無法創建有效的安全上下文(因為沒有用戶標識符可供使用)。因此,如果您的策略中沒有包含user_u(這對于許多配置是有意義的),那么您必須顯式地將所有Linux用戶添加到SELinux策略中。
SELinux還有第二個特殊用戶,系統用戶system_u,它通常用于init等所有系統進程,以及由init啟動的守護進程。從技術上講,用戶system_u沒有特殊含義,在策略語言中沒有以任何方式進行異常處理。但是,大多數現有的策略都包含這個用戶,并且系統通常在配置時希望這個SELinux用戶用于系統資源。通常,在策略中始終包含system_u是一個好主意
永遠不要使用標識符system_u創建Linux用戶帳戶。如果這樣做,該Linux用戶將能夠使用系統用戶標識符登錄,系統用戶標識符通常具有很高的特權(盡管仍然比普通Linux系統上的root權限小得多)。
六、約束
SELinux提供了一種約束機制來進一步限制策略允許的訪問,而不管策略允許規則是什么。
為了理解約束的目的,讓我們重新看看SELinux Linux安全模塊(LSM)。
我們希望進一步了解訪問決策邏輯在安全服務器中的工作方式。訪問向量緩存(AVC)由源安全標識符(SID)、目標SID和對象類三部分組成。SID是安全上下文的內部參考
1、安全上下文和SID
SELinux實現了Flask安全體系結構,該體系結構提供了實現增強訪問控制的框架,但仍然保持安全策略中立。這意味著AVC及其與LSM掛鉤的接口沒有專門綁定到類型強制(TE)和SELinux實現的其他安全策略。就AVC而言,安全標識符是對一組安全憑據的不透明惟一引用。AVC緩存由源和目標sid以及對象類標識符索引決定。
SELinux安全服務器在內部將安全上下文與SIDs聯系起來,因此,SELinux可以使用sid查找類型、用戶和角色標識符,而AVC和LSM鉤子接口可以忽略這些細節。當SELinux LSM鉤子請求訪問決策時,它們提供主題(源)和對象(目標)以及對象類的sid。AVC使用SID-SID-class三元組查找被允許的訪問,該訪問被存儲為位掩碼。當緩存丟失發生時,AVC調用安全服務器函數security_compute_av()來確定允許的訪問。
該函數的訪問決策邏輯有兩個基本步驟:
1)為type-type-class三元組創建一個表示根據TE allow規則允許的對象權限的掩碼;
2)從允許掩碼中刪除任何約束不允許的權限。
第二個步驟允許將約束作為限制策略所允許的權限的一種方法。因此,正如您所看到的,約束進一步限制了SELinux策略中允許的訪問。
SELinux有兩種類型的約束。
constraint語句是最常見的約束,允許您根據源和目標安全上下文的用戶、角色和/或類型進一步限制訪問。validatetrans語句是SELinux中最新添加的,它使您能夠基于舊的、新的和流程安全上下文進一步限制對安全上下文更改事件的訪問。
2、約束語句
約束語句有三個元素:約束應用到的對象類的集合、被約束類的權限集和約束的布爾表達式。約束由對象類組織并存儲在策略中。constraint語句允許您根據源和目標安全上下文之間的關系定義約束,從而限制指定對象類的指定權限。約束語句的完整語法如下所示:
constrain class_set perm_set expression ;
class_set一個或多個對象類。
perm_set一個或多個權限。所有權限必須對
class_set中的所有對象類有效。表達式約束的布爾表達式。
布爾表達式語法支持以下關鍵字:
t1, r1, u1 Source type, role, and user
t2, r2, u2 Target type, role, and user
約束表達式語法還支持以下操作符:
= =集合成員的或等價的
=設置不屬于或不等于
eq (Role關鍵字)的等價
dom (Role關鍵字)支配由
incomp (Role關鍵字)支配的
domby (Role關鍵字)不可比較
例子:
constrain process transition (u1 == u2) ;
首先,注意它只應用于流程對象類,并且只限制流程的轉換權限。回想一下,允許域轉換需要轉換權限;實際上,這個約束進一步限制了域轉換。現在讓我們看看約束表達式(u1 == u2)。我們看到,它要求所有域轉換的源用戶標識符和目標用戶標識符保持相同。allow rule 限制了域類型的切換; constrain 進一步限制 process類型在域切換時:安全上下文中的用戶不能改變。
回想一下前面對訪問算法的描述。當流程請求轉換權限時,AVC調用安全服務器以確定允許對三重源目標類的訪問時,前面的約束將變得有效(對于流程對象類),并將檢查源和目標安全上下文中的用戶標識符。如果用戶標識符不相同,則在將授予的訪問掩碼返回AVC之前,掩碼中表示轉換權限的位將被刪除。constraint語句允許您對安全上下文的三個元素(用戶、角色和類型)的任意組合表示約束。約束表達式將源(主題)流程和目標(對象)的上下文相互比較,并/或使用顯式名稱(例如類型或角色標識符)進行比較。
例子:
constrain process transition (r1 == r2) ;
這個約束類似于前面的語句,只是它約束的是角色標識符而不是用戶標識符。關鍵字r1和r2分別表示源角色標識符和目標角色標識符。這個約束要求角色標識符不能在域轉換上更改。
因為這兩個約束與相同的對象類和權限相關,約束表達式語法允許我們將它們組合成一個布爾表達式:
constrain process transition (u1 == u2 and r1 == r2) ;
讓我們進一步看看我們的例子。在某些情況下,我們希望允許在域轉換上更改用戶和/或角色標識符。例如,登錄過程需要將用戶和角色標識符更改為登錄用戶的標識符。登錄的SC:system_u:system_r:local_login_t當前SC:user_u:user_r:user_t。另一個例子是允許您更改角色的程序,該程序必須能夠在域轉換期間更改角色標識符。一般來說,這些程序是受信任的進程,我們需要一種方法來允許它們更改用戶/角色標識符,同時確保約束對所有其他程序都是活動的。為了實現這個目標,讓我們首先定義一種方法來識別那些受信任可以更改用戶和角色標識符的域類型。特別地,讓我們假設策略中定義了兩個屬性:privuser和privrole。前者與允許更改用戶標識符的所有類型相關聯,后者與允許更改角色標識符的類型相關聯。通過這些屬性,我們可以改變約束如下:
constrain process transition (u1 == u2 or t1 == privuser) ;
constrain process transition (r1 == r2 or t1 == privrole) ;
在這兩個語句中,t1都表示源類型。第一個語句只允許在源類型具有privuser屬性的情況下在域轉換中更改用戶標識符。同樣,如果源類型具有privrole屬性,則可以更改角色
對于約束表達式,所有操作符的左側必須是允許的關鍵字之一(例如,u1或u2),并且可能永遠不是類型、屬性、角色或用戶標識符(或標識符列表)。運算符的右側可以是一個關鍵字或一個或多個標識符名稱。
3、標簽轉換約束
SELinux支持第二條約束語句validatetrans。該語句是作為修改后的多級安全特性的一部分添加的,我們將在下一章中進行討論。通過validatetrans語句,我們可以進一步控制更改受支持對象的安全上下文的能力。
與constraint語句不同,validatetrans語句允許您將對象的新舊安全上下文相互關聯,并/或與第三個安全上下文(試圖重新標記對象的進程的安全上下文)關聯起來。因此,為該語句添加了新的關鍵字,特別是t3、r3和u3,分別表示流程安全上下文的類型、角色和用戶。*1關鍵字表示舊的安全上下文,*2關鍵字表示新的安全上下文
注意不要混淆約束和validatetrans語句之間的關鍵字關聯。對于約束語句,t1表示源(或調用流程)類型,t2表示目標(對象)類型。然而,在validatetrans語句中,t3現在是源流程類型,t1是“舊”類型,t2是“新”類型。
validatetrans語句通過與新舊安全上下文和流程的安全上下文定義基于約束的關系來限制更改指定受支持對象的安全上下文的能力。validatetrans語句的完整語法如下:
validatetrans class_set expression ;
布爾表達式語法支持以下關鍵字:
t1, r1, u1 Old type, role, and user
t2, r2, u2 New type, role, and user
t3, r3, u3 Process type, role, and user
約束表達式語法還支持以下操作符:
==集合成員的或等價的
=設置不屬于或不等于
eq(僅限Role關鍵字)的等價
dom(僅限Role關鍵字)支配
domby(僅限Role關鍵字)不受支配
incomp(僅限Role關鍵字)不可比較
假設我們有一個user_tmp_t類型,在我們的策略中,我們將其用作普通不受信任用戶程序的臨時文件的類型。我們可能希望確保具有更改所有文件標簽權限的域不會意外地將user_tmp_t作為其類型的文件重新標記為某些非常關鍵的類型(輸入shadow_t類型,這是/etc/shadow文件的類型)。這是我們的約束條件它提供了這樣的約束:
validatetrans {file lnk_file} ( t2 != shadow_t or t1 != user_tmp_t );
注意這個約束的幾個特性。我們同時包含普通文件和符號鏈接(lnk_file),因為我們不希望有人使用鏈接代替文件。該約束表示,要允許文件和符號鏈接對象更改安全上下文,只有在舊類型不是user_tmp_t的情況下,新類型才可能是shadow_t。如果舊類型是user_tmp_t,則新類型可能不是shadow_t。換句話說,任何域類型都不能被授權將用戶臨時文件重新標記為影子密碼文件的類型。
要擴展這個示例,假設有一個域類型子集,我們希望允許它將user_tmp_t重新標記為shadow_t。現在,我們創建一個屬性relabel_any,并將其分配給我們希望授予此特權的那些域類型。
validatetrans {file lnk_file}
(
( t3 == relabel_any) or
( t2 != shadow_t or t1 != user_tmp_t )
);
七、多級安全
在最近對SELinux的增強中,約束特性得到了擴展,以實現可選的多級安全(MLS)策略。MLS是另一種形式的強制訪問控制,它構建在類型強制(TE)之上。在本章中,我們將探討可選的MLS策略特性。MLS是另一種強制訪問控制形式,適用于一些安全問題,特別是與政府機密數據控制相關的安全問題。在SELinux中,MLS是類型強制的可選擴展;沒有它,MLS特性就無法實現。
7.1 安全上下文和多級安全
啟用MLS時,將使用兩個附加字段擴展安全上下文:低安全級別和高安全級別。安全級別本身有兩個字段:敏感(sensitivity)性和一組類別(categories)。敏感性是嚴格分層的,反映了一個有序的數據敏感性模型,如政府分類控制中的絕密、機密和非機密。類別是無序的,反映了數據劃分的需要。基本思想是,您既需要足夠高的靈敏度間隙,又需要正確的類別來訪問數據。
不要混淆安全級別和敏感性。安全級別是單個敏感性和一組(零或多個)類別的組合。安全級別不是分層的,使用優勢關系(dom、domby、eq、incomp)進行比較
7.2 定義安全等級
使用靈敏度語句定義靈敏度,如下所示:
sensitivity s0;
sensitivity s1;
sensitivity s2;
sensitivity s3;
這些名稱是SELinux中典型的通用敏感命名約定。
敏感性語句還支持將附加別名與敏感性關聯的能力,敏感性將被視為與核心敏感性名稱相同的名稱。例如:
sensitivity s1 alias unclassified;
這些名稱是SELinux中典型的通用敏感命名約定。
由于敏感性必須是層次性相關的,我們必須在政策中使用支配性語句指定敏感性的層次性,如下所示:
dominance { s0 s1 s2 s3 }
優勢語句按照從低到高的順序列出敏感性名稱。因此,在我們的例子中,s0小于s1, s1小于s2,以此類推。
類別的定義類似于使用類別語句定義敏感性。類別也可以有別名。下列語句是類別語句的例子:
category c0 alias blue;
category c1 alias red;
category c2 alias green;
category c3 alias orange;
category c4 alias white;
在策略語言中定義安全級別的最后一步是使用level語句定義允許的安全級別組合。level語句規定了如何將類別與敏感性聯系起來。請記住,單個敏感性和一組類別的組合構成一個安全級別。下面是level語句的一些例子:
level s0:c0.c4;
level s1:c0.c4;
level s2:c0.c4;
level s3:c0.c4;
例子:
level s0:c0.c2;
level s1:c0.c2,c4;
在本例中,s0可能只與類別c0、c1和c2相關聯;s1有c0 c1 c2 c4(但不是c3)現在,您應該已經注意到,點(.)表示類別的一個包含范圍,逗號(,)表示類別的一個非連續列表。level語句定義了哪些敏感性和類別的組合構成SELinux策略中MLS部分可接受的安全級別
僅僅因為類別的范圍是使用范圍運算符(.)指定的,這并不意味著類別是分層相關的。相反,range操作符只是一種方便地引用一組類別的方法。范圍操作符的類別順序只是聲明它們的順序,與它們的名稱隱含的任何內在順序無關。
7.3 安全上下文的MLS拓展
格式如下:
user:role:type:sensitivity[:category,...][ - sensitivity[:category,...]]
對于MLS SELinux系統,安全上下文被擴展為包括兩個安全級別:低級別或當前安全級別和高級別或清除安全級別。通常,低級別反映了流程的當前安全級別或對象中包含的數據的敏感性。高級別反映上下文中用戶標識符的清除級別(從而確定任何安全上下文的當前級別所允許的最高安全級別)或某些所謂的多級別對象所允許的最大數據范圍。
要使安全上下文有效,高級別必須始終控制低級別。此外,與敏感性相關的類別必須根據策略中的級別聲明有效。
例子:
level s0:c0.c2;
level s1:c0.c2,c4;
user_u、user_r和user_t是有效的用戶、角色和類型標識符,以下安全上下文無效:
user_u:user_r:user_t:s0 -s0:c2,c4 (c4 is invalid for s0)
user_u:user_r:user_t:s0:c0 -s0:c2 (high does not dominate the low)
八、條件策略
這里,我們將探討通過策略語句創建的條件策略,這些策略允許我們根據環境定義啟用或禁用的規則。
8.1 概述
條件策略語句使我們能夠定義僅在條件表達式定義的情況下啟用的策略規則集,條件表達式是使用定義的變量和邏輯運算符構造的邏輯表達式。讓我們看一個虛構的例子。
假設我們有一臺移動計算機,并且希望定義策略規則,使其能夠訪問特定程序的域類型(例如,myprog_t),以便在計算機停靠時僅訪問有線以太網網絡接口,在計算機未停靠時僅訪問無線網絡接口。
為了達到這個目的,我們可以寫一個條件句,如:
bool docked true;
if (docked) {
# rules to allow my_prog_t access to wired Ethernet device
} else {
# rules to allow my_prog_t access to wireless device
}
我們所要做的就是在停靠/取消停靠設備時更改布爾值(例如,正在運行的服務可能會監視此狀態并相應地設置布爾值),以啟用適當的策略規則集。
8.2 布爾變量
編寫條件策略的第一步是創建布爾變量。例如,假設我們想要配置策略,以便普通用戶使用ping程序的能力能夠被打開和關閉。我們需要定義一個布爾變量user_ping,我們將在條件表達式中使用它。
bool user_ping false;
我們使用bool語句來定義布爾變量。bool語句有兩個參數,布爾值(user_ping)的名稱及其默認值,可以為真,也可以為假。在這種情況下,默認值(false)意味著普通用戶在默認情況下不能使用ping,bool語句定義了條件布爾值及其默認值。
bool bool_name default_value;
內核通過selinux偽文件系統公開布爾值。這個偽文件系統是用戶空間和內核中的SELinux Linux安全模塊(LSM)之間的主要接口。文件系統通常安裝在/selinux/上。當前策略中定義的所有布爾變量將顯示為這個偽文件系統的布爾目錄中的文件。例如,您可以將上面定義的布爾值看作一個路徑名為/selinux/ boolies /user_ping的文件。
在運行的系統中更改布爾變量值的能力使我們能夠更改條件表達式的值,從而提供條件策略。因此,SELinux內核必須使布爾變量可用于運行更改的進程。這與策略的任何其他組件不同,后者一旦加載到內核中,在加載新的整個策略之前都是靜態的。布爾值在運行的系統上可以單獨訪問和更改。
我們使用selinux文件系統中的布爾文件來查詢和設置布爾變量的當前值。如果您查看布爾文件的內容,您總是會看到一對數字(0或1表示false或true),如下所示:
# cat /selinux/booleans/user_ping
1 1
第一個數字表示布爾變量的當前值;在這種情況下,1為真。第二個數字表示布爾變量的掛起值。當前值是內核用于布爾值和確定條件表達式值的實際值。掛起是布爾值的當前值在提交布爾值更改時將被更改的值。我們通過更改布爾的掛起值,然后將更改提交給內核,來更改布爾的當前值。
我們通過向布爾文件寫入1或0來更改掛起的值,如下所示:
# cat /selinux/booleans/user_ping
1 1
# echo 0 > /selinux/booleans/user_ping
# cat /selinux/booleans/user_ping
1 0
掛起的值現在變為0,當前值保持不變。這意味著,即使將布爾user_ping的掛起值更改為false(0),它的值仍然為true(1)。
原因是更改布爾值需要兩個步驟的提交過程。首先,更改想要更改的布爾值的掛起值,然后將掛起值提交到當前值。這允許您更改多個布爾值,然后在一步中提交所有更改。文件/selinux/commit_pending_bools是將所有布爾值的掛起值提交為當前值的接口。通過向該文件寫入1,可以實現提交,如下所示:
# echo 1 > /selinux/commit_pending_bools
# commit all pending values
# cat /selinux/booleans/user_ping
0 0
SELinux為查詢和更改布爾值提供了方便的命令,而無需記住它們的文件位置。getsebool命令將布爾值的狀態顯示為活動(TRue)或非活動(false)。例如:
# getsebool -a
docked > inactive
user_ping > active
...
我們還可以使用setsebool命令更改布爾值
# getsebool user_ping (* show current state *)
user_ping > active
# setsebool user_ping false (* change and commit current state*)
# getsebool user_ping (* show changed stated *)
user_ping > inactive
我們還可以使用setsebool命令,使用參數的另一種格式在一個事務中更改多個布爾值,如下所示:
# getsebool user_ping docked
user_ping > active
docked > inactive
# setsebool user_ping=0 docked=1
# getsebool user_ping docked
user_ping > inactive
docked > active
在策略文件中定義了布爾變量及其默認狀態。在SELinux策略語言中包含布爾值之后,出現了一個問題,即如何在不重新創建策略的情況下更改布爾值的默認狀態。因此引入了持久值的概念。SELinux實用程序使用的標準庫提供了一種方法,通過使用布爾值來維護文件,從而對布爾值進行持久更改。init進程使用此文件在系統初始化期間覆蓋策略默認值。通過這種方式,我們可以更改在重新引導期間持續存在的布爾值的當前值,而不必修改靜態SELinux策略。
8.3 條件語句
if (cond_expression)
{true_list}
[else {false_list}]
cond_expression
是一個條件表達式,由一個或多個布爾變量和邏輯運算符組成。表9-1列出了受支持的邏輯運算符。布爾變量必須使用bool語句定義。根據條件表達式的值有條件地啟用或禁用的規則列表。當條件列表為真時,將啟用規則的真列表(禁用false)。反之亦然。false列表是可選的。
九、客體標識
要使SELinux策略發揮作用,所有對象實例都必須使用安全上下文進行標記。在本節中,我們將討論將安全上下文應用于對象實例的各種方法,包括在創建對象時如何分配安全上下文,以及稍后如何修改這些標簽(稱為重標號)。
9.1 基本含義
SELinux中的所有對象從創建到銷毀都有一個相關的安全上下文。此屬性對于SELinux執行訪問控制的能力至關重要。讓我們看看文件/etc/shadow的安全上下文
# ls -Z /etc/shadow
-r------- root root system_u:object_r:shadow_t shadow
這個例子演示了為文件/etc/shadow顯示安全上下文的程序ls。與對象關聯的安全上下文(在本例中是system_u:object_r:shadow_t)是SELinux在訪問控制決策中使用的唯一屬性。從根本上說,這一點以及為所有對象分配正確的安全上下文非常重要。
SELinux策略語言包含一些特性,這些特性使標記決策自動化并在很大程度上透明。文件和域轉換的類型轉換規則,有時,標簽成為我們需要關注的問題。在系統管理、策略開發、系統安裝期間。作為政策制定者,我們必須仔細制定標簽政策聲明,以便在運行時簡化標簽管理。
對象在SELinux系統上的標記有四種基本方式:
1、策略語句:SELinux策略語言包含一些特性,比如type_transition規則,它們為對象標記指定行為
2、硬編碼的默認:大多數對象類都在對象管理器中編碼了某種類型的默認標記行為。例如,默認情況下,當進程創建新套接字時,新套接字具有與其創建進程相同的安全上下文。
3、程序需要的標記:對于一些對象類,SELinux提供了各種應用程序編程接口(api),允許程序顯式地請求標簽,包括新對象實例和現有對象實例
4、出事SID:SELinux有一組初始安全標識符(初始sid),用于標記一些對象,并在對象缺少或無效標簽時用作故障安全標簽
未完待續。。。
總結
- 上一篇: centos 安装JAVA 三种方法
- 下一篇: Maven外部依赖