淺顯易懂的 SELinux 政策實施指南

SELinux(Security-Enhanced Linux)是一款 Linux 的安全性增強模組,起初由美國國家安全局(NSA)所開發,後來則整合進 Linux 核心,成為 Linux 核心的內建模組。不過並非所有的 Linux 發行版都預設啟用了 SELinux。Red Hat 是 SELinux 的最主要支持者,預設啟用 SELinux 的發行版多半都是來自於 Red Hat 或其衍生物,例如 FedoraRHELCentOS 等等。

 

儘管 SELinux 相較於基本的 Unix-like 權限管理而言是更為嚴謹 ,但同時也顯得更為複雜,因此有不少 Linux 的使用者會傾向於直接停用它。另一方面,也有不少的使用者會讓它維持啟用,然後再根據阻擋的狀況執行特定的放行動作。然而無論是選擇啟用或停用,或許更大多數的使用者其實都對 SELinux 的工作原理一知半解,也未曾明白它真正的益處。

 

今年是 SELinux 首次釋出的十週年,一名 Red Hat 的員工 Daniel Walsh 在 opensource.com 發表了一篇文章:Your visual how-to guide for SELinux policy enforcement,該文章旨在以淺顯易懂的方式,說明 SELinux 的原理。由於內容並不涉及任何 SELinux 的指令與操作,而是純粹利用譬喻、漫畫和舉例來解釋 SELinux,因此對任何人來說應該都是很容易吸收的一篇文章。

 

以下是 DR 所翻的中文版,原版的圖文內容皆採 CC BY-SA 授權,而圖片的作者為 Máirín Duffy。

 

屬於你的 SELinux 政策實施視覺化教學指南

 

今年我們慶祝 SELinux 的十週年,這真是驚人。SELinux 第一次被導入是在 Fedora Core 3(DR 註:更精確的說法是從 FC2 就包含了,然後在 FC3 成為預設啟用),接著是在 Red Hat Enterprise Linux 4。以下則是給那些從沒用過 SELinux、或者想要有個解釋的人……

 

SELinux 是一種標籤系統,每一支程序都會被給予標籤,作業系統中的每一個檔案 / 目錄物件也都會被給予標籤。甚至是網路連接埠、裝置以及潛在的主機名稱也都有各自的標籤。我們撰寫規則去控制程序標籤對於物件(例如檔案)標籤的存取,對此我們稱之為政策,而核心會實施這些規則。有些時候這項實施會被稱為「委任式存取控制」(Mandatory Access Control,MAC)。

 

物件的擁有者並不擁有凌駕於物件安全屬性之上的處理權,標準的 Linux 存取控制是藉由擁有者 / 群組以及權限旗標例如「rwx」,這經常被稱為「自主式存取控制」(Discretionary Access Control,DAC)。SELinux 並沒有 UID 或者檔案擁有權的概念,所有事物都是由標籤控制。這表示 SELinux 系統可以限制 root 程序的權限。

 

注意:SELinux 並不會使你忽視 DAC 控制,SELinux 是一個與之並行的實施模型,應用程式必須被 SELinux 和 DAC 兩者都允許後才能進行某些活動。這或許會造成管理者的困惑,因為當有程序的權限被禁止時,管理者會以為是 DAC 的問題,而非 SELinux 標籤。

 

類型實施

讓我們略進一步的來談所謂的標籤,SELinux 的主要模型或實施方式稱為類型實施。基本上這表示我們在程序和檔案系統的物件上各自定義基於自身類型的標籤。

 

(譬喻)

想像有個系統我們需在其中定義例如貓跟狗的物件,貓跟狗都是程序類型。

 

牠們都有一個想要與之互動的物件類別稱為食物(food),而我想要為食物添加類型,成為貓食(cat_food)和狗食(dog_food)。

 

作為政策的撰寫者,我想要指示出狗擁有吃(eat)狗食(dog_chow food)的權限,而貓擁有吃(eat)貓食(cat_chow food)的權限。在 SELinux 裡我們將這些規則寫入到政策中。

 

allow cat cat_chow:food eat;

allow dog dog_chow:food eat;

 

藉由這些規則我們會允許貓程序吃標記為 cat_chow 的食物,而狗則吃標記為 dog_chow 的食物。

 

然而在 SELinux 系統中,所有事物預設都是被禁止的。這表示當狗程序想要去吃貓食(cat_chow)時,系統核心會阻止牠。

 

同樣地,貓也不被允許去接觸狗食。

 

(真實場景)

我們將 Apache 程序標記為 httpd_t,然後將 Apache 內容標記為 httpd_sys_content_t 以及  httpd_sys_content_rw_t。想像我們將信用卡資料存放在一個標記為 mysqld_data_t  的 MySQL 資料庫中。假如有一支 Apache 程序被入侵了,駭客可能會取得 httpd_t 程序的控制權並且受允許去讀取標記為  httpd_sys_content_t 的檔案,此外他還能夠寫入標記為 httpd_sys_content_rw_t 的檔案。但駭客不會被允許讀取信用卡資料(mysqld_data_t),即使該程序是由 root 執行的。在這個案例裡,SELinux 減輕了服務遭到入侵後的損害。

 

MCS 實施

(譬喻)

以上,我們分別了狗程序和貓程序,但如果你有不只一隻狗:菲多(Fido)和史巴(Spot)。而你想要禁止菲多去吃史巴的狗食。

 

一個解決方案是建立多個新類型,像是 Fido_dog 和 Fido_dog_chow。但這會很快變得不可理喻,因為其實每隻狗所需的權限幾乎都是相同的。

 

為了解決這類問題,我們開發了一種新的實施型態,稱之為「多重類別安全性」(Multi Category Security,MCS)。在 MCS 中,我們為標籤添加了其它的區塊,使得我們可以應用在狗程序和狗食上。現在我們將狗程序標記為 dog:random1(菲多)和  dog:random2(史巴)。

 

我們將狗食標記為 dog_chow:random1(菲多)和 dog_chow:random2(史巴)。

 

如果類型實施規則通過,並且完全符合任意的 MCS 標籤,那麼存取會被允許,反之則會被禁止。

 

菲多(dog:random1)若試圖去吃貓食(cat_chow:food)仍會被類型實施所禁止。

 

菲多(dog:random1)可被允許去吃屬於菲多的狗食(dog_chow:random1)。

 

菲多(dog:random1)會被禁止去吃屬於史巴的狗食(dog_chow:random2)。

 

(真實場景)

在電腦系統中我們經常會有許多的程序進行相同的存取,但我們希望它們可以分別出來,我們有些時候稱之為多重租戶環境。虛擬機器是最佳的例子。假如我有一部伺服器執行了許多虛擬機器,而當中的其中一部被入侵了,我想要防止其它的虛擬機器以及虛擬機器映像也跟著被攻擊。但在類型實施系統中,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(使用者 / 應用程式程序)皆用相同的 SELinux 類型(openshift_t)執行。由政策所定義的規則控制 Gear 類型的存取,並且由獨特的 MCS 標籤去確保每一個 Gear 都無法與其它 Gear 進行交互作用。

 

請觀看這支短片來瞭解在 SELinux 實施的情況下,OpenShift 的 Gear 取得 root 權限後會發生什麼事。

 

MLS 實施

另一種 SELinux 的實施型態則相對少用,稱為「多重級別安全性」(Multi Level Security,MLS)。這種型態早在 60 年代就被發展出來了,並主要用於可信賴式作業系統中,例如 Trusted Solaris。

 

其主要的想法是根據所使用的資料級別來控制程序,一支屬於一般機密級別的程序不應能夠讀取屬於最高機密級別的資料。

 

MLS 與 MCS 非常相似,差別在於前者增加了支配性的概念。MCS 之間的標籤必須完全符合,MLS 標籤則能夠凌駕於另一個 MLS 標籤並取得存取權限。

 

(譬喻)

這回我們不再針對不同的個體,而是針對不同的品種。假如我們有一隻灰獵犬(Greyhound)與一隻吉娃娃(Chihuahua)。

 

或許我們會想要允許灰獵犬去吃任何種類的狗食,但吉娃娃會被阻止去吃屬於灰獵犬的狗食。

 

我們將灰獵犬標記為 dog:Greyhound,而屬於牠的狗食為 dog_chow:Greyhound,並標記吉娃娃為 dog:Chihuahua,而屬於牠的狗食為 dog_chow:Chihuahua。

 

藉由 MLS 政策,MLS 的灰獵犬標籤將會凌駕於吉娃娃標籤。這表示灰獵犬(dog:Greyhound)會被允取去吃灰獵犬以及吉娃娃的狗食(dog_chow:Greyhound、dog_chow:Chihuahua)。

 

然而吉娃娃(dog:Chihuahua)並不被允許去吃灰獵犬的狗食(dog_chow:Greyhound)。

 

當然,由於類型實施仍存在的緣故,灰獵犬(dog:Greyhound)與吉娃娃(dog:Chihuahua)仍然會被禁止去吃屬於暹羅貓(Siamese)的貓食(cat_chow:Siamese),就算 MLS 類型的灰獵犬凌駕在暹羅貓之上亦是如此。

 

(真實場景)

我可能會有兩個 Apache 服務:一個執行 httpd_t:TopSecret 程序,而另一個執行 httpd_t:Secret 程序。假如 Apache 的 httpd_t:Secret 程序遭到入侵,駭客將能夠讀取標記為 httpd_sys_content_t:Secret 的內容,但仍會被禁止讀取標記為 httpd_sys_content_t:TopSecret 的內容。

 

反之如果 Apache 服務所執行的 httpd_t:TopSecret 程序遭到入侵,則 httpd_sys_content_t:Secret 的內容和 httpd_sys_content_t:TopSecret 就都能夠被讀取。

 

MLS 可應用在具有使用者級別限制的環境中,例如軍事領域。當特定使用者只被允許去取得一般機密級別的資料,而相同系統中的另一特定使用者則能夠取得最高機密級別的資料。

 

總結

SELinux 是一種強大的標籤系統,由系統核心控制個別程序的權限。類型實施是其主要的功能,這類規則藉由程序和物件的標籤來定義程序的存取權限。另外還有兩種附加的控制:MCS 和 MLS。前者的功能是可以將相同的程序類型進一步的建構出分別,而後者則能夠建構程序之間的支配性。