華文網

做人做事,安全第一!——SELinux 入門

一、前言

安全增強型 Linux(Security-Enhanced Linux)簡稱 SELinux,它是一個 Linux 內核模組,也是 Linux 的一個安全子系統。SELinux 主要由美國國家安全局開發,2.6 及以上版本的 Linux 內核都已經集成了 SELinux 模組。SELinux 的結構及配置非常複雜,而且有大量概念性的東西,

要學精難度較大。很多 Linux 系統管理員嫌麻煩都把 SELinux 關閉了。如果大家可以熟練掌握 SELinux 並正確運用,我覺得整個系統基本上可以到達“堅不可摧”的地步了(請永遠記住沒有絕對的安全)。掌握 SELinux 的基本概念以及簡單的配置方法是每個 Linux 系統管理員的必修課。

這裡把學習經驗與大家分享交流,出錯再所難免,僅供參考!如果發現錯誤的地方,可以的話麻煩指點下,特別感謝!本文的測試環境均在 CentOS 7.4.1708 系統中操作。

二、SELinux 的作用及許可權管理機制

2.1 SELinux 的作用:

SELinux 主要作用就是最大限度地減小系統中服務進程可訪問的資源(最小許可權原則)。

設想一下,如果一個以 root 身份運行的網路服務存在 0day 漏洞,駭客就可以利用這個漏洞,以 root 的身份在您的伺服器上為所欲為了。是不是很可怕?

SELinux 就是來解決這個問題的。

2.2 DAC:

在沒有使用 SELinux 的作業系統中,決定一個資源是否能被訪問的因素是:某個資源是否擁有對應用戶的許可權(讀、寫、執行)。

只要訪問這個資源的進程符合以上的條件就可以被訪問。

而最致命問題是,root 用戶不受任何管制,系統上任何資源都可以無限制地訪問。

這種許可權管理機制的主體是用戶,也稱為自主存取控制(DAC)。

2.3 MAC:

在使用了 SELinux 的作業系統中,決定一個資源是否能被訪問的因素除了上述因素之外,還需要判斷每一類進程是否擁有對某一類資源的存取權限。

這樣一來,即使進程是以 root 身份運行的,也需要判斷這個進程的類型以及允許訪問的資源類型才能決定是否允許訪問某個資源。進程的活動空間也可以被壓縮到最小。即使是以 root 身份運行的服務進程,一般也只能訪問到它所需要的資源。即使程式出了漏洞,影響範圍也只有在其允許訪問的資源範圍內。安全性大大增加。

這種許可權管理機制的主體是進程,

也稱為強制存取控制(MAC)。而 MAC 又細分為了兩種方式,一種叫類別安全(MCS)模式,另一種叫多級安全(MLS)模式。下文中的操作在沒有特殊說明的情況下均為MCS模式。在 DAC 模式下,只要相應目錄有相應使用者的許可權,就可以被訪問。而在 MAC 模式下,還要受進程允許訪問目錄範圍的限制。

三、SELinux 基本概念

SELinux決策過程

3.1 主體(Subject):可以完全等同於進程。注:為了方便理解,如無特別說明,以下均把進程視為主體。

3.2 對象(Object):被主體訪問的資源。可以是檔、目錄、埠、設備等。注:為了方便理解,如無特別說明,以下均把檔或者目錄視為物件。

3.3 策略和規則(Policy & Rule):系統中通常有大量的檔和進程,為了節省時間和開銷,通常我們只是選擇性地對某些進程進行管制。而哪些進程需要管制、要怎麼管制是由策略決定的。一套策略裡面有多個規則。部分規則可以按照需求啟用或禁用(以下把該類型的規則稱為布林型規則)。規則是模組化、可擴展的。在安裝新的應用程式時,應用程式可通過添加新的模組來添加規則。使用者也可以手動地增減規則。

在 CentOS 7 系統中,有三套策略,分別是:

targeted:對大部分網路服務進程進行管制。這是系統預設使用的策略(下文均使用此策略)。

minimum:以targeted為基礎,僅對選定的網路服務進程進行管制。一般不用。

mls:多級安全保護。對所有的進程進行管制。這是最嚴格的策略,配置難度非常大。一般不用,除非對安全性有極高的要求。

策略可以在/etc/selinux/config中設定。

3.4 安全上下文(Security Context)

安全上下文是 SELinux 的核心。安全上下文我自己把它分為「進程安全上下文」和「檔安全上下文」。

一個「進程安全上下文」一般對應多個「檔安全上下文」。只有兩者的安全上下文對應上了,進程才能訪問檔。它們的對應關係由策略中的規則決定。

檔安全上下文由檔創建的位置和創建檔的進程所決定。而且系統有一套預設值,使用者也可以對預設值進行設定。需要注意的是,單純的移動檔操作並不會改變檔的安全上下文。

安全上下文的結構及含義

安全上下文有四個欄位,分別用冒號隔開。形如:system_u:object_r:admin_home_t:s0。

用戶(User)角色(Role)類型(Type)級別(Level)進程安全上下文• 主要分兩類。

•system_u
為系統服務進程,受到管制。

•unconfined_u
為不管制進程,通常都是使用者自己開啟的,如 bash。

• 主要分兩類。

•system_r

為系統服務進程,受到管制。

•unconfined_r

為不管制進程,通常都是使用者自己開啟的,如 bash。

• 在targeted模式下

唯一一個需要關注的欄位。

• 在targeted模式下,只有兩者的類型對應上了(不代表相同),進程才能訪問檔。

• MLS 安全級別。僅在 MLS 模式下才有意義。檔安全上下文• 主要分兩類。

•system_u
為系統服務創建的檔。

•unconfined_u
為用戶自己創建的檔。

• 均為object_r,表示一個檔。

• 在targeted模式

下唯一一個需要關注的欄位。

• 在targeted模式下,只有兩者的類型對應上了(不代表相同),進程才能訪問檔。

• MLS 安全級別。僅在 MLS 模式下才有意義。

3.5 SELinux 的工作模式

SELinux 有三種工作模式,分別是:

enforcing:強制模式。違反 SELinux 規則的行為將被阻止並記錄到日誌中。

permissive:寬容模式。違反 SELinux 規則的行為只會記錄到日誌中。一般為調試用。

disabled:關閉 SELinux。

SELinux 工作模式可以在/etc/selinux/config中設定。

如果想從disabled切換到enforcing或者permissive的話,需要重啟系統。反過來也一樣。enforcing和permissive模式可以通過setenforce 1|0命令快速切換。

需要注意的是,如果系統已經在關閉 SELinux 的狀態下運行了一段時間,在打開 SELinux 之後的第一次重啟速度可能會比較慢。因為系統必須為磁片中的檔創建安全上下文(我表示我重啟了大約 10 分鐘,還以為是死機了……)。

SELinux 日誌的記錄需要借助auditd.service這個服務,請不要禁用它。

四、SELinux 基本操作

4.1 查詢檔或目錄的安全上下文

命令基本用法

ls -Z <檔或目錄>

用法舉例

查詢/etc/hosts的安全上下文。ls -Z /etc/hosts

執行結果

-rw-r--r--. root root system_u:object_r:net_conf_t:s0 /etc/hosts

4.2 查詢進程的安全上下文

命令基本用法

ps auxZ | grep -v grep | grep <進程名>

用法舉例

查詢 Nginx 相關進程的安全上下文。

ps auxZ | grep -v grep | grep nginx

執行結果

system_u:system_r:httpd_t:s0 root 7997 0.0 0.0 122784 2156 ? Ss 14:31 0:00 nginx: master process /usr/sbin/nginxsystem_u:system_r:httpd_t:s0 nginx 7998 0.0 0.0 125332 7560 ? S 14:31 0:00 nginx: worker process

4.3 手動修改檔或目錄的安全上下文

命令基本用法

chcon <選項> <檔或目錄 1> [<檔或目錄 2>...]選項功能-u <值>修改安全上下文的用戶欄位-r <值>修改安全上下文的角色欄位-t <值>修改安全上下文的類型欄位-l <值>修改安全上下文的級別欄位--reference <檔或目錄>修改與指定檔或目錄相一致的安全上下文-R遞迴操作-h修改軟連結的安全上下文(不加此選項則修改軟連結對應檔)

用法舉例

修改test的安全上下文為aaa_u:bbb_r:ccc_t:s0:

chcon -u aaa_u -r bbb_r -t ccc_t test

4.4 把檔或目錄的安全上下文恢復到預設值

命令基本用法

restorecon [選項] <檔或目錄 1> [<檔或目錄 2>...]

用法舉例

添加一些網頁檔到 Nginx 伺服器的目錄之後,為這些新檔設置正確的安全上下文。

restorecon -R /usr/share/nginx/html/

4.5 查詢系統中的布林型規則及其狀態

命令基本用法

getsebool -a

由於該命令要麼查詢所有規則,要麼只查詢一個規則,所以一般都是先查詢所有規則然後用grep篩選。

用法舉例

查詢與httpd有關的布林型規則。

getsebool -a | grep httpd

執行結果

httpd_anon_write --> offhttpd_builtin_scripting --> onhttpd_can_check_spam --> offhttpd_can_connect_ftp --> off#以下省略

4.6 開關一個布林型規則

命令基本用法

setsebool [選項] <規則名稱>

用法舉例

開啟httpd_anon_write規則。

setsebool -P httpd_anon_write on

4.7 添加目錄的預設安全上下文

命令基本用法

semanage fcontext -a -t <檔安全上下文中的類型欄位> "<目錄(後面不加斜杠)>(/.*)?"

注:目錄或檔的預設安全上下文可以通過semanage fcontext -l命令配合grep過濾查看。

用法舉例

為 Nginx 新增一個網站目錄/usr/share/nginx/html2之後,需要為其設置與原目錄相同的預設安全上下文。

semanage fcontext -a -t httpd_sys_content_t "/usr/share/nginx/html2(/.*)?"

4.8 添加某類進程允許訪問的埠

命令基本用法

semanage port -a -t <服務類型> -p <協議> <埠號>

注:各種服務類型所允許的埠號可以通過semanage port -l命令配合grep過濾查看。

用法舉例

為 Nginx 需要使用10080的埠用於 HTTP 服務。

semanage port -a -t http_port_t -p tcp 10080五、SELinux 錯誤分析和解決

5.1 認識 SELinux 日誌

當開啟了 SELinux 之後,很多服務的一些正常行為都會被視為違規行為(標題及下文中的錯誤均指違規行為)。

這時候我們就需要借助 SELinux 違規日誌來分析解決。

SELinux 違規日誌保存在/var/log/audit/audit.log中。/var/log/audit/audit.log的內容大概是這樣的。

type=LOGIN msg=audit(1507898701.391:515): pid=8523 uid=0 subj=system_u:system_r:crond_t:s0-s0:c0.c1023 old-auid=4294967295 auid=0 tty=(none) old-ses=4294967295 ses=25 res=1type=USER_START msg=audit(1507898701.421:516): pid=8523 uid=0 auid=0 ses=25 subj=system_u:system_r:crond_t:s0-s0:c0.c1023 msg='op=PAM:session_open grantors=pam_loginuid,pam_keyinit,pam_limits,pam_systemd acct="root" exe="/usr/sbin/crond" hostname=? addr=? terminal=cron res=success'...

該檔的內容很多,而且混有很多與 SELinux 錯誤無關的系統審計日誌。我們要借助sealert這個實用工具來幫忙分析(如果提示找不到命令的話請安裝setroubleshoot套裝軟體)。

5.2 使用sealert分析錯誤

命令基本用法

sealert -a /var/log/audit/audit.log

執行完命令之後,系統需要花一段時間去分析日誌中的違規行為並給出分析報告。

5.3 個人解決 SELinux 錯誤的思路

當發現一個服務出現錯誤的時候,請先檢查一下sealert的分析報告裡面是否有該服務進程名稱的關鍵字。如果沒有,說明不是 SELinux 造成的錯誤,請往其他方面排查。

接下來就是閱讀sealert的分析報告了。

首先需要瞭解的就是違規原因。如果違規原因裡面出現了該服務不該訪問的檔或資源,那就要小心了。有可能是服務的配置有問題或者服務本身存在漏洞,請優先排查服務的設定檔。

在分析報告中,對於一個違規行為,通常會有 2~3 個解決方案。請優先選擇修改布林值、設置默認安全上下文之類操作簡單、容易理解的解決方案。

如果沒有這種操作簡單、容易理解的解決方案,請先去搜尋引擎搜索一下有沒有其他更好的解決方案。

需要注意的是,可信度只是一個參考值,並不代表使用可信度最高的解決方案就一定可以解決問題。我個人感覺使用可信度越高的解決方案對系統的改動就越小。

不過請記住,在執行解決方案之前,一定要先搞清楚解決方案中的命令是幹什麼的!

最後,請謹慎使用audit2allow這個命令。這個命令的作用非常簡單粗暴,就是強制允許所遇到的錯誤然後封裝成一個 SELinux 模組,接著讓 SELinux 載入這個模組來達到消除錯誤的目的。不是萬不得已建議不要隨便使用audit2allow。

一套策略裡面有多個規則。部分規則可以按照需求啟用或禁用(以下把該類型的規則稱為布林型規則)。規則是模組化、可擴展的。在安裝新的應用程式時,應用程式可通過添加新的模組來添加規則。使用者也可以手動地增減規則。

在 CentOS 7 系統中,有三套策略,分別是:

targeted:對大部分網路服務進程進行管制。這是系統預設使用的策略(下文均使用此策略)。

minimum:以targeted為基礎,僅對選定的網路服務進程進行管制。一般不用。

mls:多級安全保護。對所有的進程進行管制。這是最嚴格的策略,配置難度非常大。一般不用,除非對安全性有極高的要求。

策略可以在/etc/selinux/config中設定。

3.4 安全上下文(Security Context)

安全上下文是 SELinux 的核心。安全上下文我自己把它分為「進程安全上下文」和「檔安全上下文」。

一個「進程安全上下文」一般對應多個「檔安全上下文」。只有兩者的安全上下文對應上了,進程才能訪問檔。它們的對應關係由策略中的規則決定。

檔安全上下文由檔創建的位置和創建檔的進程所決定。而且系統有一套預設值,使用者也可以對預設值進行設定。需要注意的是,單純的移動檔操作並不會改變檔的安全上下文。

安全上下文的結構及含義

安全上下文有四個欄位,分別用冒號隔開。形如:system_u:object_r:admin_home_t:s0。

用戶(User)角色(Role)類型(Type)級別(Level)進程安全上下文• 主要分兩類。

•system_u
為系統服務進程,受到管制。

•unconfined_u
為不管制進程,通常都是使用者自己開啟的,如 bash。

• 主要分兩類。

•system_r

為系統服務進程,受到管制。

•unconfined_r

為不管制進程,通常都是使用者自己開啟的,如 bash。

• 在targeted模式下

唯一一個需要關注的欄位。

• 在targeted模式下,只有兩者的類型對應上了(不代表相同),進程才能訪問檔。

• MLS 安全級別。僅在 MLS 模式下才有意義。檔安全上下文• 主要分兩類。

•system_u
為系統服務創建的檔。

•unconfined_u
為用戶自己創建的檔。

• 均為object_r,表示一個檔。

• 在targeted模式

下唯一一個需要關注的欄位。

• 在targeted模式下,只有兩者的類型對應上了(不代表相同),進程才能訪問檔。

• MLS 安全級別。僅在 MLS 模式下才有意義。

3.5 SELinux 的工作模式

SELinux 有三種工作模式,分別是:

enforcing:強制模式。違反 SELinux 規則的行為將被阻止並記錄到日誌中。

permissive:寬容模式。違反 SELinux 規則的行為只會記錄到日誌中。一般為調試用。

disabled:關閉 SELinux。

SELinux 工作模式可以在/etc/selinux/config中設定。

如果想從disabled切換到enforcing或者permissive的話,需要重啟系統。反過來也一樣。enforcing和permissive模式可以通過setenforce 1|0命令快速切換。

需要注意的是,如果系統已經在關閉 SELinux 的狀態下運行了一段時間,在打開 SELinux 之後的第一次重啟速度可能會比較慢。因為系統必須為磁片中的檔創建安全上下文(我表示我重啟了大約 10 分鐘,還以為是死機了……)。

SELinux 日誌的記錄需要借助auditd.service這個服務,請不要禁用它。

四、SELinux 基本操作

4.1 查詢檔或目錄的安全上下文

命令基本用法

ls -Z <檔或目錄>

用法舉例

查詢/etc/hosts的安全上下文。ls -Z /etc/hosts

執行結果

-rw-r--r--. root root system_u:object_r:net_conf_t:s0 /etc/hosts

4.2 查詢進程的安全上下文

命令基本用法

ps auxZ | grep -v grep | grep <進程名>

用法舉例

查詢 Nginx 相關進程的安全上下文。

ps auxZ | grep -v grep | grep nginx

執行結果

system_u:system_r:httpd_t:s0 root 7997 0.0 0.0 122784 2156 ? Ss 14:31 0:00 nginx: master process /usr/sbin/nginxsystem_u:system_r:httpd_t:s0 nginx 7998 0.0 0.0 125332 7560 ? S 14:31 0:00 nginx: worker process

4.3 手動修改檔或目錄的安全上下文

命令基本用法

chcon <選項> <檔或目錄 1> [<檔或目錄 2>...]選項功能-u <值>修改安全上下文的用戶欄位-r <值>修改安全上下文的角色欄位-t <值>修改安全上下文的類型欄位-l <值>修改安全上下文的級別欄位--reference <檔或目錄>修改與指定檔或目錄相一致的安全上下文-R遞迴操作-h修改軟連結的安全上下文(不加此選項則修改軟連結對應檔)

用法舉例

修改test的安全上下文為aaa_u:bbb_r:ccc_t:s0:

chcon -u aaa_u -r bbb_r -t ccc_t test

4.4 把檔或目錄的安全上下文恢復到預設值

命令基本用法

restorecon [選項] <檔或目錄 1> [<檔或目錄 2>...]

用法舉例

添加一些網頁檔到 Nginx 伺服器的目錄之後,為這些新檔設置正確的安全上下文。

restorecon -R /usr/share/nginx/html/

4.5 查詢系統中的布林型規則及其狀態

命令基本用法

getsebool -a

由於該命令要麼查詢所有規則,要麼只查詢一個規則,所以一般都是先查詢所有規則然後用grep篩選。

用法舉例

查詢與httpd有關的布林型規則。

getsebool -a | grep httpd

執行結果

httpd_anon_write --> offhttpd_builtin_scripting --> onhttpd_can_check_spam --> offhttpd_can_connect_ftp --> off#以下省略

4.6 開關一個布林型規則

命令基本用法

setsebool [選項] <規則名稱>

用法舉例

開啟httpd_anon_write規則。

setsebool -P httpd_anon_write on

4.7 添加目錄的預設安全上下文

命令基本用法

semanage fcontext -a -t <檔安全上下文中的類型欄位> "<目錄(後面不加斜杠)>(/.*)?"

注:目錄或檔的預設安全上下文可以通過semanage fcontext -l命令配合grep過濾查看。

用法舉例

為 Nginx 新增一個網站目錄/usr/share/nginx/html2之後,需要為其設置與原目錄相同的預設安全上下文。

semanage fcontext -a -t httpd_sys_content_t "/usr/share/nginx/html2(/.*)?"

4.8 添加某類進程允許訪問的埠

命令基本用法

semanage port -a -t <服務類型> -p <協議> <埠號>

注:各種服務類型所允許的埠號可以通過semanage port -l命令配合grep過濾查看。

用法舉例

為 Nginx 需要使用10080的埠用於 HTTP 服務。

semanage port -a -t http_port_t -p tcp 10080五、SELinux 錯誤分析和解決

5.1 認識 SELinux 日誌

當開啟了 SELinux 之後,很多服務的一些正常行為都會被視為違規行為(標題及下文中的錯誤均指違規行為)。

這時候我們就需要借助 SELinux 違規日誌來分析解決。

SELinux 違規日誌保存在/var/log/audit/audit.log中。/var/log/audit/audit.log的內容大概是這樣的。

type=LOGIN msg=audit(1507898701.391:515): pid=8523 uid=0 subj=system_u:system_r:crond_t:s0-s0:c0.c1023 old-auid=4294967295 auid=0 tty=(none) old-ses=4294967295 ses=25 res=1type=USER_START msg=audit(1507898701.421:516): pid=8523 uid=0 auid=0 ses=25 subj=system_u:system_r:crond_t:s0-s0:c0.c1023 msg='op=PAM:session_open grantors=pam_loginuid,pam_keyinit,pam_limits,pam_systemd acct="root" exe="/usr/sbin/crond" hostname=? addr=? terminal=cron res=success'...

該檔的內容很多,而且混有很多與 SELinux 錯誤無關的系統審計日誌。我們要借助sealert這個實用工具來幫忙分析(如果提示找不到命令的話請安裝setroubleshoot套裝軟體)。

5.2 使用sealert分析錯誤

命令基本用法

sealert -a /var/log/audit/audit.log

執行完命令之後,系統需要花一段時間去分析日誌中的違規行為並給出分析報告。

5.3 個人解決 SELinux 錯誤的思路

當發現一個服務出現錯誤的時候,請先檢查一下sealert的分析報告裡面是否有該服務進程名稱的關鍵字。如果沒有,說明不是 SELinux 造成的錯誤,請往其他方面排查。

接下來就是閱讀sealert的分析報告了。

首先需要瞭解的就是違規原因。如果違規原因裡面出現了該服務不該訪問的檔或資源,那就要小心了。有可能是服務的配置有問題或者服務本身存在漏洞,請優先排查服務的設定檔。

在分析報告中,對於一個違規行為,通常會有 2~3 個解決方案。請優先選擇修改布林值、設置默認安全上下文之類操作簡單、容易理解的解決方案。

如果沒有這種操作簡單、容易理解的解決方案,請先去搜尋引擎搜索一下有沒有其他更好的解決方案。

需要注意的是,可信度只是一個參考值,並不代表使用可信度最高的解決方案就一定可以解決問題。我個人感覺使用可信度越高的解決方案對系統的改動就越小。

不過請記住,在執行解決方案之前,一定要先搞清楚解決方案中的命令是幹什麼的!

最後,請謹慎使用audit2allow這個命令。這個命令的作用非常簡單粗暴,就是強制允許所遇到的錯誤然後封裝成一個 SELinux 模組,接著讓 SELinux 載入這個模組來達到消除錯誤的目的。不是萬不得已建議不要隨便使用audit2allow。