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