天天看點

Type enforcement(類型強制通路控制)

版權聲明:您好,轉載請留下本人部落格的位址,謝謝 https://blog.csdn.net/hongbochen1223/article/details/45271203

(一)、簡介

在SELinux中,所有的通路都要被明确的同意。SELinux預設的是沒有通路,不管Linux的使用者ID群組ID是什麼。是的,這就意味着在SELinux中沒有預設的超級使用者,不像在标準Linux中的root使用者。被同意的通路的方式是由主體的類型(也就是域)和客體的類型使用一個allow規則指定的。一個allow規則有四個元素:

1:source type(s),通常是嘗試通路的程序的域

2:target type(s),要被程序通路的客體的類型

3:object class(es),指定的允許通路的客體類别

4:permission(s),主體通路客體類别的通路方式

舉個例子,下面的規則:

allow user_t bin_t : file {read execute getattr};

這個例子展示了TE allow規則的基本文法。這個規則有兩個類型辨別符:源類型(或者是主體,或者是域),user_t;目标類型(或者是客體),bin_t。辨別符file是一個被定義在政策中的對象類型的名稱(在這個例子中,代表着一個二進制檔案)。在花括号中的permissions是一個檔案對象類别有效的permission的子集合。這條規則的翻譯是:

類型辨別符是user_t的一個程序能夠一個類型辨別符為bin_t的檔案對象進行讀,執行或者是擷取屬性。

正如我們下面将要讨論到的,在SELinux中的權限(permissions)要比标準的linux更加細化,在标準linux中隻有三個權限,rwx(可讀,可寫,可執行)。在這個例子中,read和execute和傳統的是一樣的。getattr不是很明顯。實際上,getattr權限是能夠允許調用者去檢視(不是改變)一個檔案的屬性,例如日期,時間以及自主要制通路模式。在标準Linux系統中,一個調用者僅僅需要該檔案目錄的搜查的權限就能夠檢視該檔案的這些資訊,即使他沒有對檔案讀通路的權限。

假設,user_t是一個普通的,沒有特權的使用者程序(例如一個登陸shell程序)的域類型,bin_t是一個使用者必須要有特有的安全特權才能運作的可執行程式(例如,/bin/bash)的辨別符,該規則可能就允許使用者來執行shell程式,例如bash shell。

注意:

在類型辨別符名稱中,_t是沒有特殊意義的。這個僅僅是被用在大多數SELinux政策中的一個命名習慣;隻要符合政策語言的文法,政策定義者就可以定義任何符合規範的名稱。

通過這個章節,我們經常會使用一些符号來描述允許的通路:圓代表程序,盒子代表客體,箭頭代表允許通路。例如,下面這個圖描述了被上一個allow規則允許的通路。

(二)、類型強制機制舉例

SELinux的allow規則,例如上面提到的那個例子,在SELinux中用來同意通路。面臨的問題就是,在決定成千上萬的通路,隻能允許必要的通路的時候,還能使系統正常的工作,使其盡可能的安全。

為了更加深入的探索TE機制,我們來舉一個密碼管理程式(也就是passwd)的例子。在linux中,讀取或者是修改shadow密碼檔案(/etc/shadow)是值得信賴的,在shadow檔案中,被加密的密碼儲存在裡面。密碼程式實作了他自己内部的安全政策,允許普通的使用者隻能修改他們自己的密碼,然而允許超級使用者修改任何密碼。為了完成這項可以信賴的工作,密碼程式需要有移動和重新建立shadow檔案的能力。在标準Linux中,他有這個特權,因為密碼程式可執行檔案有setuid位集合,是以,當他被其他人執行的時候,也會以超級使用者運作的(他能夠通路任何檔案)。

然而,很多程式能夠以超級使用者的身份運作(事實上,所有的程式都有可能以超級使用者的身份運作)。也就是說,任何以超級使用者的身份運作的程式都有可能修改shadow密碼檔案。TE機制讓我們做的就是確定隻有密碼程式(或者是相似的可以信任的程式)才能夠通路shadow檔案,不管運作該程式的使用者是誰。

下圖展示了使用TE機制的SELinux中,密碼程式是如何運作的。

在這個例子中,我們定義了兩種類型。passwd_t是被密碼程式所使用的一個域類型。shadow_t辨別符是shadow密碼檔案的辨別符。如果我們檢查在磁盤上這樣的一個檔案,我們将會看到下面的資訊:

# ls -Z /etc/shadow

-r—- root root system_u:object_r:shadow_t shadow

同樣,在這種政策下,檢查一個運作在密碼程式中的程序,将會顯示這樣的資訊:

#ps -Z

joe:user_r:passwd_t 16532 pts/0 00:00:00 passwd

就現在來說,你可以先忽略安全上下文中的使用者和角色元素,隻關注辨別符。

檢查在表figure 2-2中的allow規則,這個規則的目的是給程序辨別符(passwd_t)能夠通路shadow檔案辨別符的權限,該權限能夠允許程序移動或者是建立一個shadow密碼檔案。是以,再重新審視一下figure 2-2,杯描述的運作密碼程式的程序能夠成功的管理shadow密碼檔案,因為他有有效的超級使用者的使用者ID(root)(在标準linux中的通路控制),并且因為TE的allow規則允許他對shadow密碼檔案辨別符有充足的通路權限(在SELinux中的通路控制)。這兩者是必要條件,但不是充分條件。

2.2.2 域轉換的問題

如果我們需要做的事情就是允許一個程序來通路客體,例如檔案,那麼編寫一個TE政策将會是簡單的。但是我們必須需要弄清楚,如何確定一個正确的程式運作在一個有正确域類型的程序上面。例如,有一個程式以某種方式使用passwd_t域類型運作在程序中,但是這個程式是不可信的,我們不想他去通路我們的shadow密碼檔案。這可能是災難性的。這個問題會帶給我們域類型轉換的問題。

為了闡述清楚,請檢視figure 2-3,在該圖中,我們詳細闡述了以前的密碼程式的例子。在這個典型的系統中,一個使用者(叫做joe)通過登入程序登入系統,一個shell程序杯建立(例如,運作bash)。在标準linux安全中,真實有效的使用者IDS(也就是joe)是一樣的。在我們例子SELinux政策中,程序類型是user_t,user_t就是适用于普通的,不可信的使用者程序的域類型。當joe的shell運作其他程式的時候,在joe使用者被建立的新程序的域類型也會保持user_t,除非采取了一些其他的行為。那麼,joe如何修改密碼呢?

我們不希望joe的不可信的域類型user_t有直接讀或者是寫shadow密碼檔案的能力,因為這将可能會使任何程式(包括joe的shell程式)能夠檢視或者是修改重要檔案的内容。正如在之前讨論的,我們希望隻有密碼程式,并且該密碼程式僅僅以域類型passwd_t運作的時候才有這樣的通路權限。那麼問題來了,如何能夠提供一套安全可靠的,并且不唐突的機制來使域類型為user_t的joe的shell程式過渡到運作着域類型為passwd_t的密碼程式的程序。

2.2.3 回顧一下标準Linux安全中的setUID程式

在讨論如何處理域轉換的問題之前,我們先來回顧一下在标準linux中相似的問題是怎樣被處理的,也就是如何提供給joe一種安全修改他的密碼的方式。在Linux中處理這種問題的方式就是通過給passwd設定使用者辨別符(setUid)到root程式。如果你在典型的linux系統中,列出密碼程式的檔案,你将會看到下面的形式

注意關于這個清單的兩個事情。首先就是在x點處s的所有者權限。這就是所謂的setuid位,這就意味着對于任何執行這個檔案的程序來說,他的有效的UID(也就是,用于通路控制抉擇的使用者ID)将會被改變成檔案的所有者。在這個例子中,root是檔案的擁有者,是以,可運作的密碼程式将會一直以有效的root的使用者ID運作。下面的圖展示了這個流程。

當joe運作密碼程式的時候,joe的shell程式将會使用fork()系統調用來創造一個與自己相近的副本。這個副本程序依然保持着同樣的使用者ID(joe),并且依然運作shell程式。然後,在被建立之後,新的程序将會執行execve()系統調用來運作密碼程式。同時在标準linux中要求程序要對程式有可執行的權限(x),在這個例子中是正确的,因為任何人對該密碼檔案都有可執行權限。在成功執行完execve()調用後會發生兩個關鍵的事情。第一個就是運作的新程序中的shell程式将會被密碼程式替換。其二,由于setuid為被設定成了檔案擁有者,那麼有效的使用者ID從程序原來的ID改變成檔案擁有者的ID(在這個例子中就是root)。因為root能夠通路任何檔案,現在密碼程式就能夠通路shadow密碼檔案并且能夠處理來自joe的修改密碼的請求了。

setuid位的使用在建構在類unix作業系統中,并且是一個簡單并且強大的特征。然而,他也闡釋了标準linux安全方面主要的缺陷。密碼程式需要以root使用者的方式去通路shadow檔案。然後,當以root使用者運作的時候,密碼程式同樣也能夠通路任何系統資源。這同樣也違反了安全工程學的核心原則-最少權限。是以,我們必須信任密碼程式不會在系統上采取其他可能的行動。對于真正的安全應用來說,密碼程式需要大量的代碼稽核以確定他不會濫用他的權限。進一步來說,當始料未及的錯誤發生在密碼程式當中的時候,他可能就造成能夠安全漏洞,該漏洞遠遠超過通路shadow密碼檔案所造成的損失。雖然密碼程式是比較簡單和高度可信的,那麼考慮一下其他程式(包括登入程式)如果以root使用者運作的話,會怎麼樣呢?

我們真正喜歡的方式就是,確定密碼程式和其他任何一定要有權限的程式有最少的權限。簡單的說,我們希望密碼程式僅僅能夠通路shadow檔案和其他一些與密碼相關的檔案以及必要的最小系統資源。同時我希望確定除了密碼程式其他程式都不能通路shadow密碼檔案。以這樣的方式,當為使用者賬戶管理評估安全問題的時候,我們僅僅需要密碼程式(或者是相似的程式)在管理使用者賬戶方面所扮演的角色而不必考慮我們自己的其他程式、

下面講一下TE安全機制的域轉換

2.2.4 域轉換

正如剛剛顯示在figure 2-2的圖中,allow規則能夠確定passwd程序域類型(passwd_t)能夠通路shadow密碼檔案。然而,我們依然存在剛剛描述的域轉換問題。提供安全的域過渡 和setuid程式的概念是相似的,但是是在TE機制下進行的。為了闡述,我們采用setuid的例子并添加上TE。

現在我們的例子更加複雜。我們詳細的了解一下這個圖。首先注意到的是我們已經添加了之前展示的三個類型,也就是joe的shell域(user_t),密碼程式的域辨別(passwd_t),以及shadow密碼檔案辨別(shadow_t)。除此之外,我們也為passwd可執行檔案添加了檔案辨別(passwd_exec_t)。例如,列舉在磁盤上的密碼程式的安全上下文,将會得到下面的結果。

現在哦我們就有足夠的資訊來建立TE政策規則來允許密碼程式以passwd_t為域辨別運作。我們來看看上圖中的規則。第一條規則:

這條規則是允許joe的shell(user_t)初始化一個在passwd可執行檔案(passwd_exec_t)的execve()系統調用。SELinux的execute檔案權限在本質上是和标準linux檔案的x通路權限是一樣的。(shell在嘗試運作之前會統計檔案,是以也需要getattr權限)回顧一下關于shell程式是如何工作的描述。首先,他先fork一個自己的拷貝,包括完全相同的安全屬性。這個拷貝依然保持着joe的shell原始的域辨別(user_t)。是以,execute權限一定要指向原始域(也就是說,shell的域辨別)。這就是為是麼user_t是這條規則的源辨別。(Source type)

下面我們看一下第二條allow規則:

這條規則提供了通路passwd_t域的入口點(entrypoint)。entrypoint是在SELinux中相當有價值的權限。該權限所做的就是定義哪一個可執行檔案(是以,哪一個程式)可能會進入一個域。對于一個域過渡來說,新的或者是”to-be-entered”(将要被進入的)域(在這個例子中,是passwd_t)一定要有通路可執行檔案的entrypoint,用于過渡到新的域辨別。在這個例子中,假設僅僅passwd可執行檔案被标志為passwd_exec_t,僅僅辨別passwd_t有passwd_exec_t的entrypoint權限,這樣就僅僅password程式能夠運作在passwd_t域辨別中。這是一個非常強大的安全控制。

警告:

entrypoint權限的概念是非常重要的。如果你不能完全了解前述的例子,請在繼續向下閱讀之前重新讀一遍。

現在我們看一下最後一個規則:

這是第一條我們所見到的不提供對檔案客體通路的allow規則。在這個執行個體中,客體類是process,也就是代表程序的對象類。回顧一下所有的系統資源都被封裝在客體類中。這個概念也适用于程序。在最後一條規則中,權限是transition通路。這個權限程序的安全上下文的辨別發生改變。原始的辨別(user_t)一定要有transition權限才能被允許轉換成新的辨別(passwd_t)。

這三個規則一塊提供了域轉換發生的必要條件。為了能使一個域轉換成功,所有的這三個條件必須得滿足。是以,當下列的三個條件都滿足的時候,一個域轉換才被允許。

1:程序新的域辨別有對可執行檔案辨別的entrypoint權限

2:程序目前(或者是過去的)域辨別有對入口點檔案辨別的execute權限

3:程序目前的域辨別有對新的域辨別的transition的權限

當在TE政策中這三個所有的權限都被同意了,一個域轉換才會發生。進一步講,對在可執行檔案entrypoint權限的使用,我們就有能力去嚴格控制哪一個程式能夠運作在給定的域辨別上。execvte()系統調用時改變域辨別的唯一的方式,讓政策定義者來控制個人程式的通路權限,而不管調用程式的使用者是誰。

現在問題就是joe如何表明自己想要進行域轉換。上述的規則僅僅是允許域轉換,他們不會指令他。有一些方式能使程式設計人員或者是使用者能夠明确的要求域轉換(如果被允許的話)。joe所想要做的就是運作密碼檔案,他希望系統能夠確定他能夠執行。我們需要一種方式來使系統能夠預設初始化一個域轉換。

2.2.5 預設的域轉換 : type_transition 語句

為了支援域轉換預設發生(正如我們密碼程式例子中一樣),我們需要介紹一個新的規則,type transtion規則(type_transtion)。這個規為SELinux政策提供了一種方式,如果一個明顯的轉換沒有被要求的話,需要指定一個應該被嘗試的預設的轉換。我們來為allow規則添加下面一個tyoe transition規則:

這條規則的文法與allow規則是不同的。他依然有源和目标辨別(user_t 和 passed_t),并且也存在客體類(process)。然而,沒有權限,我們有一個第三方辨別,預設辨別(passwd_t).

type_transition規則用于與預設辨別該表相關的多個不同的目标。就現在來說,我們關心的是有process作為他的客體類的type_transitin。這樣的規則導緻一個要嘗試的預設的域轉換。type_transition顯示出,預設情況下,在一個exece()系統調用中,如果一個調用的程序的域辨別為user_t,并且一個可執行檔案的辨別是passwd_exec_t(上面figure的例子),一個域轉換到一個新的域(passwd_t)将會被嘗試。

type_transition規則允許政策定義者在沒有明确的使用者輸入的時候,預設初始化一個域轉換。這使得TE機制不會讓使用者感到很強制。在我們例子中,joe不想知道任何關于通路控制和辨別的事情;他想要去修改密碼。系統和政策定義者可以使用type_transition規則來為使用者執行這些轉換。

一定要記住,一個type_transition規則會導緻一個預設的域轉換嘗試,但是他不會允許他。為了能夠保證域轉換的成功完成,你依然需要提供域轉換所必須的三個辨別,無論他是預設初始化的還是作為一個使用者明确的要求發生的。

上一篇: selinux第一節
下一篇: C實作萬年曆

繼續閱讀