天天看點

linux學習筆記-SELinux

幾乎可以肯定每個人都聽說過 SELinux (更準确的說,嘗試關閉過),甚至某些過往的經驗讓您對 SELinux 産生了偏見。不過随着日益增長的 0-day 安全漏洞,或許現在是時候去了解下這個在 Linux 核心中已經有8年曆史的強制性通路控制系統(MAC)了。

SELinux 與強制通路控制系統

SELinux 全稱 Security Enhanced Linux (安全強化 Linux),是 MAC (Mandatory Access Control,強制通路控制系統)的一個實作,目的在于明确的指明某個程序可以通路哪些資源(檔案、網絡端口等)。

強制通路控制系統的用途在于增強系統抵禦 0-Day 攻擊(利用尚未公開的漏洞實作的攻擊行為)的能力。是以它不是網絡防火牆或 ACL 的替代品,在用途上也不重複。

舉例來說,系統上的 Apache 被發現存在一個漏洞,使得某遠端使用者可以通路系統上的敏感檔案(比如 <code>/etc/passwd</code> 來獲得系統已存在使用者),而修複該安全漏洞的 Apache 更新更新檔尚未釋出。此時 SELinux 可以起到彌補該漏洞的緩和方案。因為 /etc/passwd 不具有 Apache 的通路标簽,是以 Apache 對于 <code>/etc/passwd</code> 的通路會被 SELinux 阻止。

相比其他強制性通路控制系統,SELinux 有如下優勢:

控制政策是可查詢而非程式不可見的。

可以熱更改政策而無需重新開機或者停止服務。

可以從程序初始化、繼承和程式執行三個方面通過政策進行控制。

控制範圍覆寫檔案系統、目錄、檔案、檔案啟動描述符、端口、消息接口和網絡接口。

那麼 SELinux 對于系統性能有什麼樣的影響呢?根據 Phoronix 在 2009 年使用 Fedora 11 所做的橫向比較來看,開啟 SELinux 僅在少數情況下導緻系統性能約 5% 的降低。

SELinux 是不是會十分影響一般桌面應用及程式開發呢?原先是,因為 SELinux 的政策主要針對伺服器環境。但随着 SELinux 8年來的廣泛應用,目前 SELinux 政策在一般桌面及程式開發環境下依然可以同時滿足安全性及便利性的要求。 以剛剛釋出的 Fedora 15 為例,筆者在搭建完整的娛樂(包含多款第三方原生 Linux 遊戲及 Wine 遊戲)及開發環境(Android SDK + Eclipse)過程中,隻有 Wine 程式的首次運作時受到 SELinux 預設政策的阻攔,在圖形化的“SELinux 故障排除程式”幫助下,點選一下按鈕就解決了。

了解和配置 SELinux

1. 擷取目前 SELinux 運作狀态

<code>getenforce</code>

可能傳回結果有三種:<code>Enforcing</code>、<code>Permissive</code> 和 <code>Disabled</code>。Disabled 代表 SELinux 被禁用,Permissive 代表僅記錄安全警告但不阻止可疑行為,Enforcing 代表記錄警告且阻止可疑行為。

目前常見發行版中,RHEL 和 Fedora 預設設定為 Enforcing,其餘的如 openSUSE 等為 Permissive。

2. 改變 SELinux 運作狀态

<code>setenforce [ Enforcing | Permissive | 1 | 0 ]</code>

該指令可以立刻改變 SELinux 運作狀态,在 Enforcing 和 Permissive 之間切換,結果保持至關機。一個典型的用途是看看到底是不是 SELinux 導緻某個服務或者程式無法運作。若是在 setenforce 0 之後服務或者程式依然無法運作,那麼就可以肯定不是 SELinux 導緻的。

若是想要永久變更系統 SELinux 運作環境,可以通過更改配置檔案 <code>/etc/sysconfig/selinux</code> 實作。注意當從 Disabled 切換到 Permissive 或者 Enforcing 模式後需要重新開機計算機并為整個檔案系統重新建立安全标簽(<code>touch /.autorelabel &amp;&amp; reboot</code>)。

3. SELinux 運作政策

配置檔案 <code>/etc/sysconfig/selinux</code> 還包含了 SELinux 運作政策的資訊,通過改變變量 <code>SELINUXTYPE</code> 的值實作,該值有兩種可能:<code>targeted</code> 代表僅針對預制的幾種網絡服務和通路請求使用 SELinux 保護,<code>strict</code> 代表所有網絡服務和通路請求都要經過 SELinux。

RHEL 和 Fedora 預設設定為 <code>targeted</code>,包含了對幾乎所有常見網絡服務的 SELinux 政策配置,已經預設安裝并且可以無需修改直接使用。

若是想自己編輯 SELinux 政策,也提供了指令行下的政策編輯器 <code>seedit</code> 以及 Eclipse 下的編輯插件 <code>eclipse-slide</code> 。

4. coreutils 工具的 SELinux 模式

常見的屬于 coreutils 的工具如 <code>ps</code>、<code>ls</code> 等等,可以通過增加 <code>Z</code> 選項的方式獲知 SELinux 方面的資訊。

如 <code>ps auxZ | grep lldpad</code>

<code>system_u:system_r:initrc_t:s0 root 1000 8.9 0.0 3040 668 ? Ss 21:01 6:08 /usr/sbin/lldpad -d</code>

如 <code>ls -Z /usr/lib/xulrunner-2/libmozjs.so</code>

<code>-rwxr-xr-x. root root system_u:object_r:lib_t:s0 /usr/lib/xulrunner-2/libmozjs.so</code>

以此類推,<code>Z</code> 選項可以應用在幾乎全部 <code>coreutils</code> 工具裡。

Apache SELinux 配置執行個體

1. 讓 Apache 可以通路位于非預設目錄下的網站檔案

首先,用 <code>semanage fcontext -l | grep '/var/www'</code> 獲知預設 <code>/var/www</code> 目錄的 SELinux 上下文:

<code>/var/www(/.*)? all files system_u:object_r:httpd_sys_content_t:s0</code>

從中可以看到 Apache 隻能通路包含 <code>httpd_sys_content_t</code> 标簽的檔案。

假設希望 Apache 使用 <code>/srv/www</code> 作為網站檔案目錄,那麼就需要給這個目錄下的檔案增加 <code>httpd_sys_content_t</code> 标簽,分兩步實作。

首先為 /srv/www 這個目錄下的檔案添加預設标簽類型:<code>semanage fcontext -a -t httpd_sys_content_t '/srv/www(/.*)?'</code> 然後用新的标簽類型标注已有檔案:<code>restorecon -Rv /srv/www</code> 之後 Apache 就可以使用該目錄下的檔案建構網站了。

其中 <code>restorecon</code>在 SELinux 管理中很常見,起到恢複檔案預設标簽的作用。比如當從使用者主目錄下将某個檔案複制到 Apache 網站目錄下時,Apache 預設是無法通路,因為使用者主目錄的下的檔案标簽是 <code>user_home_t</code>。此時就需要 <code>restorecon</code>将其恢複為可被 Apache 通路的 <code>httpd_sys_content_t</code> 類型:

<code>restorecon reset /srv/www/foo.com/html/file.html context unconfined_u:object_r:user_home_t:s0-&gt;system_u:object_r:httpd_sys_content_t:s0</code>

2. 讓 Apache 偵聽非标準端口

預設情況下 Apache 隻偵聽 80 和 443 兩個端口,若是直接指定其偵聽 888 端口的話,會在 <code>service httpd restart</code> 的時候報錯:

<code>Starting httpd: (13)Permission denied: make_sock: could not bind to address [::]:888</code>

<code>(13)Permission denied: make_sock: could not bind to address 0.0.0.0:888</code>

<code>no listening sockets available, shutting down</code>

<code>Unable to open logs</code>

這個時候,若是在桌面環境下 SELinux 故障排除工具應該已經彈出來報錯了。若是在終端下,可以通過檢視 /var/log/messages 日志然後用 sealert -l 加編号的方式檢視,或者直接使用 <code>sealert -b</code> 浏覽。無論哪種方式,内容和以下會比較類似:

<code>SELinux is preventing /usr/sbin/httpd from name_bind access on the tcp_socket port 888.</code>

<code>***** Plugin bind_ports (92.2 confidence) suggests *************************</code>

<code>If you want to allow /usr/sbin/httpd to bind to network port 888</code>

<code>Then you need to modify the port type.</code>

<code>Do</code>

<code># semanage port -a -t PORT_TYPE -p tcp 888</code>

<code>***** Plugin catchall_boolean (7.83 confidence) suggests *******************</code>

<code>If you want to allow system to run with NIS</code>

<code>Then you must tell SELinux about this by enabling the 'allow_ypbind' boolean.</code>

<code>setsebool -P allow_ypbind 1</code>

<code>***** Plugin catchall (1.41 confidence) suggests ***************************</code>

<code>If you believe that httpd should be allowed name_bind access on the port 888 tcp_socket by default.</code>

<code>Then you should report this as a bug.</code>

<code>You can generate a local policy module to allow this access.</code>

<code>allow this access for now by executing:</code>

<code># grep httpd /var/log/audit/audit.log | audit2allow -M mypol</code>

<code># semodule -i mypol.pp</code>

可以看出 SELinux 根據三種不同情況分别給出了對應的解決方法。在這裡,第一種情況是我們想要的,于是按照其建議輸入:

<code>semanage port -a -t http_port_t -p tcp 888</code>

之後再次啟動 Apache 服務就不會有問題了。

這裡又可以見到 <code>semanage</code> 這個 SELinux 管理配置工具。它第一個選項代表要更改的類型,然後緊跟所要進行操作。詳細内容參考 Man 手冊

3. 允許 Apache 通路建立私人網站

若是希望使用者可以通過在 <code>~/public_html/</code> 放置檔案的方式建立自己的個人網站的話,那麼需要在 Apache 政策中允許該操作執行。使用:

<code>setsebool httpd_enable_homedirs 1</code>

<code>setsebool</code> 是用來切換由布爾值控制的 SELinux 政策的,目前布爾值政策的狀态可以通過 <code>getsebool</code> 來獲知。

預設情況下 setsebool 的設定隻保留到下一次重新開機之前,若是想永久生效的話,需要添加 <code>-P</code> 參數,比如:

<code>setsebool -P httpd_enable_homedirs 1</code>

總結

希望通過這一個簡短的教程,掃除您對 SELinux 的誤解甚至恐懼,個人感覺它并不比 iptables 政策複雜。如果希望您的伺服器能有效抵擋 0-day 攻擊時,那麼 SELinux 或許就是一個值得考慮的緩和方案。

繼續閱讀