SELinux 入門:理解 Linux 中的強制訪問控制與安全策略
一、概述
我們通常依靠傳統(tǒng)的安全措施,如強密碼、權(quán)限設(shè)置和防火墻來保護(hù)Linux系統(tǒng)。但有時,我們需要更精細(xì)的控制,比如管理進(jìn)程可能執(zhí)行的操作。這時候,SELinux(安全增強型Linux)就派上用場了。
SELinux最初由美國國家安全局(NSA)開發(fā),后來發(fā)布給開源社區(qū)。它讓系統(tǒng)管理員能夠定義特定的訪問策略,以控制進(jìn)程和用戶與系統(tǒng)資源的交互方式。
在本教程中,我們將探討SELinux是什么、它如何工作以及它的重要性。

二、SELinux到底是什么?
SELinux是一個內(nèi)置于Linux內(nèi)核的安全模塊,它在常規(guī)的Unix風(fēng)格權(quán)限系統(tǒng)之外提供額外的訪問控制。它在防范權(quán)限提升、配置錯誤和零日漏洞攻擊方面發(fā)揮著關(guān)鍵作用。
在安全性至關(guān)重要的環(huán)境中,SELinux的作用尤為突出。無論是運行Web服務(wù)器、數(shù)據(jù)庫還是容器化應(yīng)用,SELinux都可能決定威脅是被遏制還是導(dǎo)致整個系統(tǒng)淪陷。
要真正理解SELinux,了解它與標(biāo)準(zhǔn)Linux安全模型的區(qū)別是很有必要的。
1. 傳統(tǒng)權(quán)限(DAC)存在的問題
在Linux中,自主訪問控制(DAC)就是那些控制誰可以對文件執(zhí)行何種操作的“讀-寫-執(zhí)行”權(quán)限,它們構(gòu)成了標(biāo)準(zhǔn)的安全層。簡單來說,文件或進(jìn)程的所有者可以決定誰能獲得訪問權(quán)限。
雖然這種方式很靈活,但它也可能成為一個薄弱環(huán)節(jié)。如果惡意程序設(shè)法獲得了控制權(quán),它或許能夠利用這些自主權(quán)限擴大破壞范圍。
例如,若一個用戶擁有某個腳本,該用戶可以決定誰能執(zhí)行這個腳本。如果特權(quán)用戶(如root)或被入侵的進(jìn)程獲得了控制權(quán),它就有可能訪問或修改系統(tǒng)上的任何資源。傳統(tǒng)上,root用戶可以繞過DAC檢查。
2. 強制訪問控制(MAC)的解決方案
SELinux帶來的重大轉(zhuǎn)變在于它改變了訪問控制的工作方式。大多數(shù)管理員和用戶都非常熟悉DAC,在這種機制下,文件所有者有決定權(quán)。而SELinux則向內(nèi)核中添加了MAC。
在MAC機制下,是操作系統(tǒng)(而非單個用戶)嚴(yán)格執(zhí)行由管理員定義的系統(tǒng)級安全策略。每一個系統(tǒng)調(diào)用、每一次訪問嘗試,都會依據(jù)這一策略進(jìn)行檢查。
更重要的是,即便是root用戶也必須遵守該策略。如果root用戶的操作超出了已定義的策略范圍,SELinux可以對其進(jìn)行限制。換句話說,這是一種更為嚴(yán)格的安全機制。我們可以阻止對文件、進(jìn)程和資源的未授權(quán)訪問或修改,即便是來自超級用戶賬戶的操作也不例外。
3. 默認(rèn)拒絕原則
SELinux的MAC方法遵循默認(rèn)拒絕原則。
簡而言之,如果SELinux規(guī)則沒有明確允許某項特定操作或訪問,那么該操作或訪問將被自動拒絕。這種“默認(rèn)拒絕”的立場本身就通過減少攻擊面提供了極大的安全優(yōu)勢。
4. MAC與DAC如何相輔相成
SELinux并不會取代由chmod或chown管理的基本文件權(quán)限,相反,它以特定的順序與這些權(quán)限協(xié)同工作,提供更深入且強制性的控制。
當(dāng)一個進(jìn)程試圖訪問某個文件時,系統(tǒng)會首先檢查DAC策略規(guī)則。只有當(dāng)這些基本權(quán)限允許訪問時,SELinux才會介入并評估其安全策略(MAC)。
這一順序意味著SELinux扮演著第二個檢查點的角色。這為那些DAC級別可能過于寬松,或者被入侵的進(jìn)程設(shè)法繞過DAC的場景提供了額外保護(hù)。
三、SELinux核心
啟用SELinux的系統(tǒng)依靠關(guān)鍵的安全概念來指導(dǎo)訪問決策。讓我們看看這些原則如何增強Linux系統(tǒng)的安全性。
1. 安全上下文(標(biāo)簽)
SELinux會為系統(tǒng)上的每個文件、用戶和進(jìn)程分配一個安全上下文(也稱為安全標(biāo)簽)。這個上下文或標(biāo)簽是一組屬性,SELinux用它來確定訪問權(quán)限。簡單來說,這些標(biāo)簽就像是“名稱標(biāo)簽”,表明哪些操作是允許的,哪些是不允許的。
安全上下文由四個部分組成(用戶:角色:類型:級別)。下面我們來看看每個部分的作用:
- 用戶:映射到一個或多個Linux用戶,并定義用戶可以承擔(dān)哪些角色,例如user_u或unconfined_u(與操作系統(tǒng)用戶不同)
- 角色:限制特定用戶或類型可以執(zhí)行的操作,定義被分配到某個角色的用戶可以訪問哪些類型(SELinux分配的角色名稱帶有_r后綴,如system_r)
- 類型:進(jìn)程的域和文件的類型,它定義了進(jìn)程和文件之間如何交互(所有文件和運行中的進(jìn)程都被分配一個以_t結(jié)尾的類型,例如,Web服務(wù)器進(jìn)程的類型是httpd_t,/var目錄中文件的類型是var_t)
- 級別(可選):多級安全(MLS)系統(tǒng)中的 clearance 級別范圍,用于設(shè)置敏感級別,如s0或s1
現(xiàn)在,我們在包含文件的目錄上運行l(wèi)s -Z命令,看看安全上下文的一些示例:
$ ls -Z
-rw-------. root root system_u:object_r:httpd_sys_content_t:s0 index.html
drwxrwxrwx. root root unconfined_u:object_r:admin_home_t:s0 backup在這里,該命令列出了文件的所有者(root)以及其讀寫執(zhí)行權(quán)限。此外,-Z選項還包含了每個條目的安全上下文的四個部分(用戶、角色、類型和安全級別),例如system_u:object_r:httpd_sys_content_t:s0。
2. 策略規(guī)則
SELinux使用策略模塊來定義每個進(jìn)程可以執(zhí)行的操作。每一個可能的操作(例如X類型的進(jìn)程讀取Y類型的文件)都需要有明確的規(guī)則允許,否則SELinux會拒絕該操作。正如我們前面提到的,SELinux默認(rèn)禁止所有操作,除非明確允許。
例如,一條策略規(guī)則可能會規(guī)定“允許httpd_t進(jìn)程讀取httpd_sys_content_t文件”。如果我們嘗試執(zhí)行規(guī)則中未涵蓋的操作,SELinux會阻止該操作并記錄拒絕信息。
設(shè)置策略規(guī)則時,我們需要遵循基本語法:
<規(guī)則類型> <主體> <對象>:<對象類別> <權(quán)限>;下面我們來分解每個部分的含義:
- 規(guī)則類型:SELinux應(yīng)采取的操作,通常是allow(允許)、dontaudit(不審計)或neverallow(從不允許)
- 主體:請求訪問的進(jìn)程的域或類型
- 對象:被訪問資源的類型
- 對象類別:對象的類別,如file(文件)、dir(目錄)、tcp_socket(TCP套接字)
- 權(quán)限:被允許的操作,如read(讀?。?、write(寫入)、open(打開)
例如,我們可以看一個簡單的策略規(guī)則示例:
ALLOW apache_process apache_log:FILE READ;這條規(guī)則簡單地允許標(biāo)有apache_process標(biāo)簽的進(jìn)程讀取標(biāo)有apache_log標(biāo)簽的日志文件。
3. 布爾值
如果我們想在不編輯安全策略的情況下關(guān)閉一條規(guī)則,該怎么辦呢?
SELinux布爾值是一個開關(guān),它允許在不重寫整個SELinux策略的情況下改變規(guī)則的行為。例如,一個常見的布爾值是httpd_can_network_connect。默認(rèn)情況下,它可能是關(guān)閉的,因此Web服務(wù)器(httpd_t)不能建立出站網(wǎng)絡(luò)連接。
讓我們看看如何使用setsebool命令將其開啟:
$ setsebool -P httpd_can_network_connect on通過將上述布爾值設(shè)置為on,SELinux允許相應(yīng)的訪問,而無需修改策略文件。此外,我們可以使用等效的數(shù)值0-1來代替on-off選項。
實際上,SELinux自帶了許多這樣的布爾值,用于控制諸如允許FTP寫入訪問、使用NFS等操作,以便在運行時調(diào)整規(guī)則。我們可以使用getsebool -a命令列出所有規(guī)則:
$ getsebool -a | less
abrt_anon_write --> off
abrt_handle_event --> off
abrt_upload_watch_anon_write --> on
antivirus_can_scan_system --> off
antivirus_use_jit --> off
auditadm_exec_content --> on
authlogin_nsswitch_use_ldap --> off
authlogin_radius --> off
authlogin_yubikey --> off
awstats_purge_apache_log_files --> off
:這里,輸出內(nèi)容可能很長,所以最好將其通過管道傳輸?shù)絣ess命令,以便逐頁滾動查看。
4. 模式
SELinux可以在三種模式下運行,每種模式提供不同級別的安全控制:
- enforcing(強制模式)(0):主動阻止違規(guī)行為
- permissive(寬容模式)(1):記錄違規(guī)行為但不阻止
- disabled(禁用模式):完全關(guān)閉SELinux,系統(tǒng)退回到正常的DAC權(quán)限
我們可以使用getenforce命令檢查當(dāng)前的SELinux模式:
$ getenforce
Enforcing在這種情況下,SELinux處于強制模式。
現(xiàn)在,我們使用setenforce命令將其切換到寬容模式:
$ setenforce 0這里的0是寬容模式的模式ID。相反,1是強制模式的ID。
值得注意的是,setenforce命令的設(shè)置在重啟后不會保留。不過,我們可以直接編輯SELinux配置文件(/etc/selinux/config)來使更改持久化。此外,編輯該配置文件也是切換到禁用模式的方法。
四、為什么SELinux很重要?
看起來Linux的文件權(quán)限(讀、寫、執(zhí)行)和用戶所有權(quán)應(yīng)該足以保證系統(tǒng)的安全。當(dāng)然,對于簡單的設(shè)置來說,通常確實如此。但是,一旦我們運行復(fù)雜的面向互聯(lián)網(wǎng)的服務(wù),標(biāo)準(zhǔn)的訪問權(quán)限就無法覆蓋所有場景了。
SELinux的一個主要優(yōu)勢是它能夠在安全漏洞出現(xiàn)時限制損害范圍。
假設(shè)Web服務(wù)器(Apache httpd)被黑客攻擊。在傳統(tǒng)權(quán)限機制下,攻擊者可能會讀取/etc目錄中的敏感文件、修改/var/www目錄中的腳本,以及訪問用戶數(shù)據(jù)。
下面我們來看一個簡單的例子,了解SELinux如何基于文件標(biāo)簽阻止即使是root用戶的訪問。
首先,我們在root用戶的主目錄中創(chuàng)建一個測試文件:
$ echo "secret" > /root/zfile現(xiàn)在,我們使用chcon命令更改該文件的SELinux標(biāo)簽:
$ chcon -t admin_home_t /root/zfile在這里,我們?yōu)?root/zfile分配了admin_home_t類型,這并不是供Web服務(wù)器訪問的類型。
最后,我們檢查Apache是否能夠訪問該文件:
$ runcon -t httpd_t -- cat /root/testfile
cat: /root/zfile: Permission denied我們使用runcon -t命令在不同的SELinux上下文(httpd_t,即Apache運行的域)下運行cat /root/zfile命令。即便cat命令是以root身份運行的,SELinux也會介入并阻止它。























