Linux中國

看漫畫學 SELinux 強制策略

今年是我們一起慶祝 SELinux 紀念日的第十個年頭了(LCTT 譯者註:本文發表於 2013 年)。真是太難以置信了!SELinux 最初在 Fedora Core 3 中被引入,隨後加入了紅帽企業版 Linux 4。從來沒有使用過 SELinux 的傢伙,你可要好好兒找個理由了……

SElinux 是一個標籤型系統。每一個進程都有一個標籤。操作系統中的每一個文件/目錄 客體 object 也都有一個標籤。甚至連網路埠、設備,乃至潛在的主機名都被分配了標籤。我們把控制訪問進程的標籤的規則寫入一個類似文件的客體標籤中,這些規則我們稱之為 策略 policy 。內核強制實施了這些規則。有時候這種「強制」被稱為 強制訪問控制體系 Mandatory Access Control (MAC)。

一個客體的擁有者對客體的安全屬性並沒有自主權。標準 Linux 訪問控制體系,擁有者/分組 + 許可權標誌如 rwx,常常被稱作 自主訪問控制 Discretionary Access Control (DAC)。SELinux 沒有文件 UID 或擁有權的概念。一切都被標籤控制,這意味著在沒有至高無上的 root 許可權進程時,也可以設置 SELinux 系統。

注意: SELinux 不允許你摒棄 DAC 控制。SELinux 是一個並行的強制模型。一個應用必須同時支持 SELinux 和 DAC 來完成特定的行為。這可能會導致管理員迷惑為什麼進程被拒絕訪問。管理員被拒絕訪問是因為在 DAC 中有些問題,而不是在 SELinux 標籤。

類型強制

讓我們更深入的研究下標籤。SELinux 最主要的「模型」或「強制」叫做 類型強制 type enforcement 。基本上這意味著我們根據進程的類型來定義其標籤,以及根據文件系統客體的類型來定義其標籤。

打個比方

想像一下在一個系統里定義客體的類型為貓和狗。貓(CAT)和狗(DOG)都是 進程類型 process type

Image showing a cartoon of a cat and dog.

我們有一類希望能與之交互的客體,我們稱之為食物。而我希望能夠為食物增加類型:cat_food (貓的食物)和 dog_food(狗的食物)。

Cartoon Cat eating Cat Food and Dog eating Dog Food

作為一個策略制定者,我可以說一隻狗有許可權去吃狗糧(dog_chow),而一隻貓有許可權去吃貓糧(cat_chow)。在 SELinux 中我可以將這條規則寫入策略中。

![allow cat cat_chow:food eat; allow dog dog_chow:food eat](/data/attachment/album/201703/22/062658sy57lyjjiwa6sjws.png "SELinux rule")

allow cat cat_chow:food eat;

允許 貓 貓糧:食物 吃;

allow dog dog_chow:food eat;

允許 狗 狗糧:食物 吃;

有了這些規則,內核會允許貓進程去吃打上貓糧標籤 cat_chow 的食物,允許狗去吃打上狗糧標籤 dog_chow 的食物。

Cartoon Cat eating Cat Food and Dog eating Dog Food

此外,在 SELinux 系統中,由於禁止是默認規則,這意味著,如果狗進程想要去吃貓糧 cat_chow,內核會阻止它。

同理,貓也不允許去接觸狗糧。

![Cartoon cat not allowed to eat dog fooda](/data/attachment/album/201703/22/062659zpiwk3p9wp757559.png "Cartoon cat not allowed to eat dog fooda")

現實例子

我們將 Apache 進程標為 httpd_t,將 Apache 上下文標為 httpd_sys_content_thttpdsys_content_rw_t。假設我們把信用卡數據存儲在 MySQL 資料庫中,其標籤為 msyqld_data_t。如果一個 Apache 進程被劫持,黑客可以獲得 httpd_t 進程的控制權,從而能夠去讀取 httpd_sys_content_t 文件並向 httpd_sys_content_rw_t 文件執行寫操作。但是黑客卻不允許去讀信用卡數據(mysqld_data_t),即使 Apache 進程是在 root 下運行。在這種情況下 SELinux 減輕了這次闖入的後果。

多類別安全強制

打個比方

上面我們定義了狗進程和貓進程,但是如果你有多個狗進程:Fido 和 Spot,而你想要阻止 Fido 去吃 Spot 的狗糧 dog_chow 怎麼辦呢?

![SELinux rule](/data/attachment/album/201703/22/062659u3sdkpmni8d40psv.png "SELinux rule")

一個解決方式是創建大量的新類型,如 Fido_dogFido_dog_chow。但是這很快會變得難以駕馭因為所有的狗都有差不多相同的許可權。

為了解決這個問題我們發明了一種新的強制形式,叫做 多類別安全 Multi Category Security (MCS)。在 MCS 中,我們在狗進程和狗糧的標籤上增加了另外一部分標籤。現在我們將狗進程標記為 dog:random1(Fido)dog:random2(Spot)

Cartoon of two dogs fido and spot

我們將狗糧標記為 dog_chow:random1(Fido)dog_chow:random2(Spot)

![SELinux rule](/data/attachment/album/201703/22/062700e56zebiqghzbdbxa.png "SELinux rule")

MCS 規則聲明如果類型強制規則被遵守而且該 MCS 隨機標籤正確匹配,則訪問是允許的,否則就會被拒絕。

Fido (dog:random1) 嘗試去吃 cat_chow:food 被類型強制拒絕了。

Cartoon of Kernel (Penquin) holding leash to prevent Fido from eating cat food.

Fido (dog:random1) 允許去吃 dog_chow:random1

Cartoon Fido happily eating his dog food

Fido (dog:random1) 去吃 spot(dog_chow:random2)的食物被拒絕。

Cartoon of Kernel (Penquin) holding leash to prevent Fido from eating spots dog food.

現實例子

在計算機系統中我們經常有很多具有同樣訪問許可權的進程,但是我們又希望它們各自獨立。有時我們稱之為 多租戶環境 multi-tenant environment 。最好的例子就是虛擬機。如果我有一個運行很多虛擬機的伺服器,而其中一個被劫持,我希望能夠阻止它去攻擊其它虛擬機和虛擬機鏡像。但是在一個類型強制系統中 KVM 虛擬機被標記為 svirt_t 而鏡像被標記為 svirt_image_t。 我們允許 svirt_t 可以讀/寫/刪除標記為 svirt_image_t 的上下文。通過使用 libvirt 我們不僅實現了類型強制隔離,而且實現了 MCS 隔離。當 libvirt 將要啟動一個虛擬機時,它會挑選出一個 MCS 隨機標籤如 s0:c1,c2,接著它會將 svirt_image_t:s0:c1,c2 標籤分發給虛擬機需要去操作的所有上下文。最終,虛擬機以 svirt_t:s0:c1,c2 為標籤啟動。因此,SELinux 內核控制 svirt_t:s0:c1,c2 不允許寫向 svirt_image_t:s0:c3,c4,即使虛擬機被一個黑客劫持並接管,即使它是運行在 root 下。

我們在 OpenShift 中使用類似的隔離策略。每一個 gear(user/app process)都有相同的 SELinux 類型(openshift_t)(LCTT 譯註:gear 為 OpenShift 的計量單位)。策略定義的規則控制著 gear 類型的訪問許可權,而一個獨一無二的 MCS 標籤確保了一個 gear 不能影響其他 gear。

請觀看下面的視頻來看 OpenShift gear 切換到 root 會發生什麼。

多級別安全強制

另外一種不經常使用的 SELinux 強制形式叫做 多級別安全 Multi Level Security (MLS);它開發於上世紀 60 年代,並且主要使用在受信操作系統上如 Trusted Solaris。

其核心觀點就是通過進程使用的數據等級來控制進程。一個 secret 進程不能讀取 top secret 數據。

MLS 很像 MCS,除了它在強制策略中增加了支配的概念。MCS 標籤必須完全匹配,但一個 MLS 標籤可以支配另一個 MLS 標籤並且獲得訪問。

打個比方

不討論不同名字的狗,我們現在來看不同種類。我們現在有一隻格雷伊獵犬和一隻吉娃娃。

Cartoon of a Greyhound and a Chihuahua

我們可能想要允許格雷伊獵犬去吃任何狗糧,但是吉娃娃如果嘗試去吃格雷伊獵犬的狗糧可能會被嗆到。

我們把格雷伊獵犬標記為 dog:Greyhound,把它的狗糧標記為 dog_chow:Greyhound,把吉娃娃標記為 dog:Chihuahua,把它的狗糧標記為 dog_chow:Chihuahua

Cartoon of a Greyhound dog food and a Chihuahua dog food.

使用 MLS 策略,我們可以使 MLS 格雷伊獵犬標籤支配吉娃娃標籤。這意味著 dog:Greyhound 允許去吃 dog_chow:Greyhounddog_chow:Chihuahua

![SELinux rule](/data/attachment/album/201703/22/062702xszf8yzat9ry58zh.png "SELinux rule")

但是 dog:Chihuahua 不允許去吃 dog_chow:Greyhound

Cartoon of Kernel (Penquin) stopping the Chihahua from eating the greyhound food.  Telling him it would be a big too beefy for him.

當然,由於類型強制, dog:Greyhounddog:Chihuahua 仍然不允許去吃 cat_chow:Siamese,即使 MLS 類型 GreyHound 支配 Siamese。

Cartoon of Kernel (Penquin) holding leash to prevent both dogs from eating cat food.

現實例子

有兩個 Apache 伺服器:一個以 httpd_t:TopSecret 運行,一個以 httpd_t:Secret 運行。如果 Apache 進程 httpd_t:Secret 被劫持,黑客可以讀取 httpd_sys_content_t:Secret 但會被禁止讀取 httpd_sys_content_t:TopSecret

但是如果運行 httpd_t:TopSecret 的 Apache 進程被劫持,它可以讀取 httpd_sys_content_t:Secret 數據和 httpd_sys_content_t:TopSecret 數據。

我們在軍事系統上使用 MLS,一個用戶可能被允許讀取 secret 數據,但是另一個用戶在同一個系統上可以讀取 top secret 數據。

結論

SELinux 是一個功能強大的標籤系統,控制著內核授予每個進程的訪問許可權。最主要的特性是類型強制,策略規則定義的進程訪問許可權基於進程被標記的類型和客體被標記的類型。也引入了另外兩個控制手段,分離有著同樣類型進程的叫做 MCS,而 MLS,則允許進程間存在支配等級。

*所有的漫畫都來自 Máirín Duffy

作者簡介:

Daniel J Walsh - Daniel Walsh 已經在計算機安全領域工作了將近 30 年。Daniel 於 2001 年 8 月加入紅帽。

via: https://opensource.com/business/13/11/selinux-policy-guide

作者:Daniel J Walsh 譯者:xiaow6 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國