2012年11月20日 星期二

SELinux 基礎與實務 (Security Enhanced Linux Basics)

SELinux(Security Enhanced Linux)為美國國家安全局(National Security Agency)於2000年以GPL授權方式所推出的安全性功能,它提供了以政策為基礎(Policy based)的強制性存取控制機制(Mandatory Access Control;MAC)。SEllinux目前採用Linux Security Modules (LSM)架構的方式整合在Linux Kernel 內的安全性機制,藉以強化Linux系統的安全性並提高攻擊的困難度。

傳統以來,UNIX/Linux系統均採用自行決定存取控制模式(Discretionary access control)來管理檔案目錄的存取,這意謂著資源的擁有者(使用者、群組)可以根據自己的偏好或意志來決定其所擁有的資源可被誰來執行何種存取動作,亦即擁有者可以自由變更所擁有資源的存取權限,沒有他人或其它機制可以避免擁有者設定有安全性疑慮(如 chmod +rwx ~)的家目錄權限,另一方面,傳統的UNIX系統管理員帳戶root也是無所不能(omnipotent),一旦被有心人士破解就可能為所欲為,可能導致了喪失系統的私密性、完整性與可用性(CIA),所以在DAC存取控制的系統下,當使用者或root不慎的執行一個有問題的軟體或惡意程式時,其所提供的保護相當有限而不足,而SELINUX則彌補了DAC機制的安全性缺失,提供了一個較能夠符合最低權限授予原則(Least Privilege)的Linux系統。

簡言之,SELinux透過訂立所有程序與物件的安全性政策規則,經由核心控制主體與物件的存取動作,一旦使用者設定不當或執行有問題軟體時將可提供較高的保護並降低損害風險。

RedHat Enterprise/CentOS Linux4版後均已內建啟用了SELinux,本文將以最新的6版來說明SELinux 如何運作以及基本設定和管理工作。

SELinux存取控制機制與名詞

首先認識存取控制機制中通常會牽涉到的三個基本名詞:

主體 (Subject)

一個可以請求存取物件的主動單位,可能是使用者,群組、程式或處理程序(an active entity that requests access to an object),在SELinux內的主體通常指的是程序。

物件 (Object)

一個包含有用訊息而可以被存取的被動目標及對象(passive entity that contains info or data),物件可能是電腦、資料庫、檔案目錄等可被使用的資源。

存取模式 (Access Model)

表示主體與物件間的互動關係及架構,常見的存取控制模式有自行決定存取控制模式(Discretionary access control;DAC)、強制性存取控制 (Mandatory Access Control;MAC)、角色基礎的存取控制模式 (Role-based access control;RBAC)、規則為基礎的存取控制 (Rule-based access control )、Lattice-based access control: 等,

SELinux的安全性模式組合了型態強制模式(Type Enforcement;TP)、角色為基礎的存取控制模式,以及選擇性的多層級模式(Multi-Level Security Model)三種。不過本文將只著眼在RedHat/CentOS預設targeted政策的型態強制模式。

由於SELinux強制存取模式的重點在於指定每個主體與物件一個安全性本文,所以我們先從認識SELinux安全性本文談起。

◎ 安全性本文(Security Context)及標記 (Label)
安全性本文可說是SELinux的核心觀念,因為舉凡每個主體(程序)或物件(檔案、目錄、通訊埠....)均會被標記(label)以安全性本文(context),如果以檔案目錄而言,這些標記被存放在檔案系統的延伸屬性,若針對程序或通訊埠而言,則由核心負責管理這些標記於記憶體內,因此SELinux也可謂是一個標記為基礎的安全性系統(Labeling Sytem)。
SELinux的安全性本文使用下面三~五個標記:

使用者身份角色類型 [:敏感度:分類 ]
範例:
system_uobject_radmin_home_ts0:c0.c128

1. 使用者身份

SELinux會維護執行程序的使用者身份,這與Linux的使用者身份是不同的,而在預設的目標政策(targeted policy)下,只會維護著最少量的使用者身份,重要者有三:

  • system_u —系統程序(System processes)
  • root — 系統管理員(System administrator)
  • user_u — 所有登入使用者(All login users)

您可以利用 "semanage user -l" 命令來列出目前的SELinux使用者身份。

2. 角色

角色被用來對類型分組,所以您可以在政策中指定某個角色能夠執行某項類型,所以它是SELinux提供"角色為基礎存取控制模式"的基礎,如果是檔案,這個角角欄位會是object_r,如為程序您可能會看到system_r或sysadm_r角色,這個欄位在預設的目標政策並沒被真正使用,但在嚴格政策(strict policy)和MLS政策上是重要的。

3. 類型

安全性本文第三個欄位是類型,這是最要的安全全本文標記,也是實現型態強制的核心,例如/usr/sbin/httpd就被標記為"httpd_exec_t"這個類型,在大部份的SELinux政策規則中,均在於定義那些主體(subject)類型可以如何存取那些物件類型。

一般而言,我們通常只處理前面三個,第四與第五個標記是為了支援多層級(MLS)模式所提供的選擇性標記,而第三個標記-類型最為重要,因為它是SELinux實現強制存取控制機制的核心標記,而且RedHat/CentOS Linux預設的政策-targeted也只使用這個標記來實現型態強制。

SELinux在許多Linux指令後附加上 "-Z" 選項以便可以觀看到安全性本文內的標記,譬如下圖利用 ls -Z、id -Z、ps –Z 命令分別顯示了檔案、使用者和執行程序的安全本文與每個標記。

lsZ1

類型強制 (Type Enforcement)

類型強制(Type Enforcement:TE)為SELINUX機制用來真正決定是否某項動作會被允許的機制,一般而言,類型強制乃是依據主體的類型、物件的類型、物件的類別以及所執行的動作來產生"允許"或"拒絕"的安全性結果,在SELinux的用語上,領域(Domain)通常用來表示某(些)程序的安全性本文(通常是類型宣告),可用來確認程序的權限,而類型(Type)用來表示特定資源被賦予的類型標記(Label),例如passwd 命令檔案被標記為 passwd_exec_t 類型,而執行中的passwd程序其領域為 passwd_t。
如下圖示:一個程序是否能夠順利的完成存取物件的動件將需要由二個安全性本文來決定--程序的安全性本文和物件的安全性本文,另一個可能影響到到存取動作的決定因素為物件的分類(Object class),例如檔案物件可能有高達十多種權限動作的等級(讀內容、讀屬性、附加、寫入...。),所以當某程序企圖存取某物件時,將查看SELinux政策內有關於程序本文內的"類型(Type)"和物件本文的"類型(Type)"的規則,然後產生一個存取物件權限等級的YES/NO的清單,稱為存取向量(Access Vector),而這個存向量向將決定程序目前所執行的物件存取動作是允許或禁止的。

typeenforcement

在類型強制中,SELinux必需明確定義允許的規則,這通常包括四部分組成:

  1. 來源類型(Source type):通常是企圖存取的程序領域類型(Domain Type)
  2. 目標類型 (target type):允許存取的物件類型
  3. 物件類別 (object class):存取所應用的類別
  4. 權限(Permission):允許存取的類型
    例如: allow user_t bin_t : file {read execute getattr};
             allow passwd_t shadow_t : file { create ioctl read getattr lock write setattr append link unlink rename };

下圖說明了SELinux 類型強制的過程,某使用者登入後企圖執行passwd命令變更密碼,由於在SElinux政策內存在規則,允許來源的類型user_t可對目的檔案類型passwd_exec_t執行操作。

te1

◎ SElinux政策

SELinux政策是一群宣告與規則,指示SELinux核心那些存取行動是可被允許,換言之,政策內的規則描述了主體和物件的存取權限與存取方式,通常涵蓋使用者、程序,檔案和設備間的存取規則,而RedHat/CentOS Linux的規則是以套件方式提供--selinux-policy-<version>.noarch.rpmSelinux,這個規則資料庫會被載入核心內,支援相當細分化(fine grained)的存取控制,得以控制主體和物件彼此間的存取動作。

新版的RedHAT/Centos/Fedora Linux 提供了二種SELinux政策類型—targeted(預設)與mls,預設的targeted政策主要目的在於提供一些較普及的網路服務(Daemon)(如httpd, dhcpd, named,mysqld,squid,winbind....)具有另一層的強制存取控制機制來強化其安全性,所以他只會影響到一些網路應用程式,而非全部,而這些受影響的網路Daemon執行在自己的領域(domain)內,例如 httpd執行在httpd_t領域,而named執行在named-t領域內,若政策內未定義的網路服務則使用unconfined_t領域,因此系統程序或網路服務執行在unconfined_t領域內則只會使用標準的Linux DAC方式來控制存取。

RedHat Enterprise 5後則推出了另一個更嚴格的政策-mls(Multi Level Security Protection),它整合了Bell Lapadule安全性模型和型態強制(Type Enforcement),並啟用了安全性本文的第四個標記-敏感度,所以這個政策不僅控管著何種安全性型態是否能夠執行那些動作,還可以針對特定的敏感等級進行存取控制。(早期還有一個strict政策可以控制系統上所有的主體與物件的存取行為,由於相當複雜,因此目前版本的RedHat Enterprise已不再支援)。

您可以編輯SELinux組態檔/etc/selinux/config內的"SELINUXTYPE=targeted | mls "項目在決定使用那個政策類型。

◎ 布林(Booleans)
布林值是SELinux執行階段的設定值,管理人員可以依據需求來切換布林值,以便在不需要撰寫新的政策下即可以改變SELinux政策的行為,若您需要檢視或變更可用的布林值可使用圖形介面的system-config-selinux或命令工具-getsebool和setsebool。

使用與設定SELinux

SElinux的運作雖然複雜,但一般而言,由於大部份的使用者並不需要自行撰寫或編譯政策,也不會採用MLS政策,所以純粹就使用SELinux並讓它能夠順利運作以強化系統安全性的目的而言,您通常只需要學會下列幾項組態設定、檢視命令以及如何進行診斷工作即可。

  • 關閉或啟用SELinux運作模式 - setenforce、getenforce、/etc/selinux/config
  • 檢視安全性本文與標記 - 基本命令 -Z
  • 變更檔案的安全性本文 – chcon
  • 問題診斷與排除 (Troubleshooting) – sealert、/var/log/audit/audit.log
  • 顯示或設定SELinux布林值 – semanage –l、getsebool、setsebool
  • 查詢政策與規則 - seinfo、sesearch
  • 還原檔案或目錄為預設的SElinux安全性本文 - restorecon
  • 使用semanage fcontext 管理安全性本文 - semanage fcontext

由於Linux版本上的差異以及安裝時所選擇的套件不同,所以並非吾人所須要的SELinux管理工具均會存在每部啟用SELinux的系統,一般而言,為了管理、設定和診斷SELinux,您最好檢查並確認您的RedHat/CentOS系統上是否已經安裝底下的套件:

  • libselinux-utils :包含了getenforce, getsebool, setenforce ...等工具
  • coreutils :包含變更檔案安全性本文工具-chcon
  • setroubleshoot-server, setroubleshoot:支援SELinux的診斷工具
  • policycoreutils-python: semanage工具
  • setools-console: 包括了許多有用的SELinux工具, findcon, seinfo, sesearch, replcon.....等

關閉或啟用SELinux運作模式

SElinux支援三種基本的運作模式:

  1. 強制執行(Enforcing):這是預設模式,此模式將啟用並執行Selinux的安全性政策、一旦違反政策將會禁止存取並記錄
  2. 許可(Permissive):在此模式雖然啟用SELinux但並不會執行SELinux安全政策,一旦違反政策只提供警告及記錄,但動作仍然允許繼續,這個模式適合用來診斷SELinux問題 。
  3. 停用(Disabled):關閉SELinux

您可以透用下列三種方式來了解或檢視系統目前的SELinux執行狀況:

  1. 檢視SELiunx組態檔-- /etc/selinux/config 檔案 (為 /etc/selinux/config的符號連結檔) 
  2. 執行 sestatus命令
  3. 執行 getenforce命令
    下圖顯示了目前系統上的SELinux已強制執行中。
    selinuxstatus

若您希望暫時在強制執行(Enforcing) 模式和許可(Permissive)模式之間予以切換,則可以執行setenforce命令(或 echo 1|0 > /selinux/enforce )來變更SELinux狀態,然後以getenforce命令來顯示並確認目前的SELinux模式。

# setenforce 0   (或 echo 0 > /selinux/enforce)
# getenforce
Permissive

# setenforce 1    (或 echo 1 > /selinux/enforce)
# getenforce
Enforcing

但若要每次開機時啟用或停用在某特定模式或狀態,則您必需要直接修改/etc/sysconfig/selinux檔案,編輯 "SELINUX=enforcing | permissive | disabled"項目。


檢視安全性本文與標記

由於SELinux是利用主體與物件的安全性本文為基礎來進行存取控制,所以您必需要能夠查看檔案目錄、程序或網路服務、連接埠目前的安全性本文,特別是第三個欄位-型態通常是判斷存取拒絕的主要關鍵標記,當然如前面所述,利用 "-Z"選項通常是最常用檢視方式,下圖以Apache網站服務為例:Apache的執行檔案標記和組態檔案標記分別為httpd_exec_t型態、httpd_config_t型態,主目錄標記為httpd_sys_content_t型態、啟動指令檔的型態為httpd_initrc_exec_t、而執行的處理程序則是httpd_t。就型態強制的莧念而言,一個標記為httpd_t的執行程序允許讀取標記為httpd_config_t的檔案。

selinux_cmd3


變更檔案的安全性本

有時候您可能需要改變檔案安全性本文內的標記,這時候您可以用chcon命令,chcon使用選項為:

chcon 用以變更檔案的SELinux的安全性本文
     -R:遞迴變更檔案和目錄的安全性本文
     --reference filename:使用 filename的安全性本文為參考值而非直接指定內容值
     -u:設定 user標記值
     -r:設定role標記值
     -t:設定型態標記值

舉著例子來說明chcon 的使用時機及用法,假若Angie在自己的家目錄撰寫好網頁程式後,再以管理員身份將撰寫完成的網頁搬移至網站主目錄下(/var/www/html)並變更檔案的擁有者與群組,然而卻發現所有用戶端均發生禁止而無法下載網頁,查看Apache的錯誤記錄檔顯示了權限不足的問題,所以再以ls  -Z觀看可順利下載和無法下載的不同點為何,故可判斷標準的使用者群組權限(DAC)並沒有問題,而是SELinux的型態不正確所導致。

selinux_err1

解決上述的問題只需要利用chcon來更改為正確的檔案SELinux型態即可:

chcon_all


SELinux 問題診斷與排除方法

當SELinux決定允許或拒絕存取時會將結果寫到快取區,此快取稱為存取向量快取(Access Vector Cache;AVC),而拒絕存取的訊息則會被記錄下來,但RHEL 6/CentOS 6以後版本的拒絕記錄可能被記錄在不同的位置,端看系統執行的Daemon而定。而這個拒絕記錄通常是目錄診斷SELinux問題的主要根據。

Daemon狀態 拒絕記錄的位置
auditd=on (預設) /var/log/audit/audit.log
auditd=off , rsyslogd=on /var/log/messages
setroubleshootd=on,rsyslogd=on,auditd=on /var/log/audit/audit.log

為了方便診斷 SELinux 的問題,建議安裝SELinux的問題診斷套件—setroubleshoot (yum –y install setroubleshoot* )並且重啟動auditd服務,當日後一旦發生拒絕存取時即可利用 "sealert –a /var/log/audit/audit.log"命令來顯示記錄的原因和建議解決方法。

設定SELinux布林值

使用SELinux布林值允許您變更部份執行時期的SELinux政策,例如允許服務存取NFS檔案系統而不需要重新載入或重新編譯政策,您可以使用getsebool命令搭配-a選項來顯示所有的SELinux布林值,此外,您也可以利用 "semanage boolean –l" 檢視布林值並且提供額外描述。

getsebool1

接下來,舉個實際範例來說明如何利用setsebool -P命令來變更布林值。
Apache網站有個眾所週知的個人網站功能,相信很多用過Apache網站者均曾經啟用並設定過這項功能,其設定也相當簡單:首先,修改httpd.conf組態檔,新增下列一行:"UserDir  public_html",接下來讓使用者只需在其主目錄下創造 public_html子目錄並在此子目錄底下存放自己撰寫的網頁,再加以變更目錄存取權限755和網頁權限644權限,爾後,他人即可透過類似的網址 http://servertname/~username  連接上個人網站。但若在啟用SELinux執行模式的系統下,這項功能將可能遭受禁止存取的錯誤。如下圖所示,當管理員啟用了個人網站功能而使用者tom也正確的在其家目錄底下的public_html子目錄提供了個人網頁且檔案系統存取權限也沒有問題,但當有人企圖瀏覽其網頁時卻得到了禁止(forbidden)的錯誤,排除了Apache網站設定與傳統檔案系統存取權限設定問題後,其它可能的存取權限問題即是SELinux的問題所導致的,但原因為何?如何加以解決呢?此時SELinux的拒絕存取記錄就是解決問題的利器了,您可以利用"sealert –a /var/log/audit/audit.log"來取得禁止存取的原因和建議。

sealert1

sealert所顯示的建議明確指示您若要讓httpd程序可以讀取使用者的內容需要啟用"httpd_read_user_content"這個布林值,此外,若要讓httpd可以讀取使用者家目錄,您還需要啟用"httpd_enable_homedirs"布林值。所以依據建議與說明執行二個SELinux布林值的變更後,tom的個人網站立即可被瀏覽下載而不再產生SELinux的禁止錯誤網頁了。

setsebool1

當您使用setsebool –P後,其實SELinux將其布林值寫入/etc/selinux/targeted/modules/active/booleans.local檔案內,並重新產生整個/etc/selinux/targeted目錄內容,請注意不要直接編輯這個booleans.local檔案,因為並不會有任何作用,要變動SELInux布林值請使用 setsebool –P才會生效。


還原檔案或目錄為預設的SElinux安全性本文

根據前面的經驗可知,SELinux 的安全性本文在檔案的複製/搬移時可能會產生變動,因此需要使用 chcon命令來重新變更為所希望的安全性本文(特別是型態標記),不過有時候較簡單的處理方式倒是利用另一個重要命令-- restorecon 來還原檔案和目錄為預設的安全性本文,不過檔案目錄如此之多, restorecon 如何會知道每個檔案或目錄的預設 SELinux 安全性本文呢?答案是Selinux將每個目錄的預設安全性本文以正規化表達方式記錄在 /etc/selinux/targeted/contexts/files/file_contexts這個檔案內,這個檔案內目前有超過四百個設定,當您下達restorecon命令時將會從這個檔案來查詢並決定其預設的安全性本文。如下圖所示,利用restorecon命令將/var/www/html目錄下所有檔案還原成此目錄該有的安全性本文。

restorecon1

使用semanage fcontext 管理安全性本文

semanage命令是另一個要的SELinux管理指令,它是個複雜的政策管理工具,可以讓您在無需修改或重新編譯政策原始檔的情況下就可設定SELinux政策內特定元素,不過本文無法介紹完整的segmant命令用法,而只是針對目錄檔案的預設安全性本文的變更用法,因為上一節已提及許多檔案目錄均有預設的安全性本文,但使用者是否可以修改或移除預設的安全性本文,甚至對於新建的目錄也可以替其設定預設的安全性本文,答案是肯定的,只需要藉助semanage fcontext指令搭配 -a, -d, -m, -e 選項就可以對檔案或目錄新增、移除、修改預設安全性本文或設定等同某檔案的預設安全性本文,底下再舉個Apache網站的實例來說明semanage fcontext的使用方法。

Apache網站可以支援別名目錄,讓網站用戶所輸入的URL路徑名稱與真實目錄名稱完全無關,這通常需要您在httpd.conf檔案內使用"Alias"指引命令來定義別名目錄,然後再替它新增<Directory>或<Location>設定段,這對許多Apache管理員而言是個很尋常的設定,但如果您的機器啟用了SELinux,情況就會稍為複雜些,例如管理員建立了一個URL別名為docs的目錄,指向檔案系統的真實目錄 /documents並且灳建立了正確對應的<Location>設定段,完成後測試別名目錄連線,卻發現拒絕存取結果,經由檢查拒絕記錄結果與建議,發現有二個建議解決方案,第一項建議為應該還原預設安全性本文,第二個建議則建議產生本機政策模組,本文並不打算處理較複雜的政策模組產生問題,但由於別名目錄是自行新增的目錄,SELinux並無提供預設安全性本文,而方案一要求還原預設安全性本文如何著手呢?

vdirerror

答案是我們應該先替別名目錄新增預正確的預設安全性本文,然後還原此安全性本文即可,但緊接下來的問題是如何新增預設正確的預設安全性本文,您可以使用semanage fcontext命令搭配-a –t 或 –a -e選項,使用-t選項需要了解並輸入正確的型態為何, -e選項只要設定等同某個目錄的型態可,所以筆者通常偏好使用-a -e的方法。

1. semanage fcontext –a –t httpd_sys_content_t  /documents

2. semanage fcontext –a –e /var/www /documents

一旦設定預設型態標記後,此時只不過將此別名目錄的型態寫入檔案/etc//etc/selinux/targeted/contexts/files/file_contexts.subs或file_contexts.local,您還必需要輸入restorecon –v  /documents後,其安全性本文才會真正套用在目錄上生效。

semanageequal1


查詢SELinux政策與規則

整個SELinux的運作主要依賴政策與規則來強制型態執行存取控制,所以有時候您可能須要查詢政策狀況或規則內容,這時就得利用 seinfo與sesearch工具。

seinfo是SELinux的政策查詢工具,允許您檢查正在執行的SELinux政策內物件(如使用者、角色、類型、布林...),其一般的用法為:

  • 檢查目前政策的統計及狀態資料
  • 檢查是否某個特定的類型已被定義 (用以決定是否需要載入額外的政策模組)以及相關的屬性
  • 檢查是否某個特定的角色存在以及其被指定的類型
  • 檢查某標記是否存在

下圖顯示了一些常用的seinfo執行例子,詳細完整的用法請參考線上輔助手冊。

seinfo

另一個sesearch工具則可以更進一步的查詢政策內的規則,藉以了解為何某些動作不被允許或者是否某種操作是可被允許的,不過它的使用也有點複雜,完整的選項與說明請自行參考線上手冊,下圖為筆者常用的部份選項範例。

sesearch4


SELinux圖形介面工具-system-config-selinux

本文的SELinux相關的設定與管理動作均利用命令列工具進行之, 其實CentOS有提供SELinux圖形介面工具—system-config-selinux,但這並非預設安裝的程式,您須要安裝 policycoreutils-gui套件後才能夠使用,圖形介面的用法很直接,在此不再贅言。

ystem-config-selinux

結語

SELinux提供Linux系統一個強化安全性和更難以攻擊的選擇性機制,導入了強制性存取控制模式以型態強制的方式來確保最低權限賦予原則的達成,但SELinux最大的問題及障礙在於其複雜度,其較高的學習曲線經常讓大部份IT人員卻步,因而直接停用SELinux,除此之外,啟用SELinux也可能會影響到系統效能,但在資訊安全領域上,使用方便性、效率和安全性原本就為取捨的問題,所以Linux系統是否要導入並啟用SELinux,首重於系統安全性需求與風險的評估,若是軍方、政府機構專門用來處理機密性等級的資料,或是商業組織用以執行商業機密的系統,建議應該啟用SELinux,不過您得先弄清楚SELinux的基礎技術並知道如何設定與管理,至於一般的Linux系統,若基於使用與管理設定的方便性以及效率的考量高於安全性,則可以關閉SElinux。