1. 程式人生 > >鳥哥的Linux私房菜讀書筆記--SELinux初探

鳥哥的Linux私房菜讀書筆記--SELinux初探

1、什麼是SELinux

security Enhanced Linux,SELinux,字面意思是安全強化的linux

<1>當初設計的目標:避免資源的誤用

SELinux是由美國安全域性(NSA)開發的,目的在與因為很多企業界發現,通常系統出現問題的原因大部分在於內部員工的資源誤用所導致的,實際由外部發動的攻擊反而沒有那麼嚴重。SELinux是在程序、檔案等細部許可權設定依據的一個核心模組,由於啟動網路服務的也是程序,因此能夠控制網路服務能否存取系統資源的一道關卡。

<2>傳統檔案許可權與賬號關係:自主式訪問控制DAC

當某個程序想要對檔案進行存取時,系統會根據程序的擁有者/群組,並比對檔案的許可權,若通過許可權檢查就可以存取該檔案了,這種存取檔案系統的方式被稱為自主式訪問控制(discretionary Access Control,DAC),依據程序的擁有者與檔案資源的rwx許可權來決定有無存取能力,DAC的訪問困擾:

· root 具有最高的許可權:如果不小心某支程序被有心人士取得, 且該程序屬於 root 的許可權,那麼這支程序就可以在系統上進行任何資源的存取!真是要命! · 使用者可以取得程序來變更檔案資源的訪問許可權:如果你不小心將某個目錄的許可權設定為 777 ,由於對任何人的許可權會變成 rwx ,因此該目錄就會被任何人所任意存取!

<3>以政策規則訂定特定程序讀取特定檔案:委任式訪問控制,MAC

DAC的困擾就是當使用者取得程序後,可以藉由這支程序與自己預設的許可權來處理他自己的檔案資源,如果該使用者對Linux系統不熟悉,可能會導致資源誤用的問題,為了避免DAC容易發生的問題,SELinux匯入委任式訪問控制MAC

MAC,可以針對特定的程序與特定的檔案資源來進行許可權的管控,即使你是root,在是用哪個不同的程序的時,你所取得的許可權不一定是root,而是根據該程序的設定而設定的,由此,針對控制的主體就變成了程序而不是使用者

左圖是沒有 SELinux 的 DAC 存取結果,apache 這隻 root 所主導的程序,可以在這三個目錄內作任何檔案的新建與修改。右邊則是加上 SELinux 的 MAC 管理的結果,SELinux 僅會針對 Apache 這個『 process 』放行部份的目錄, 其他的非正規目錄就不會放行給 Apache 使用!因此不管你是誰,就是不能穿透 MAC 的框框!

2、 SELinux 的運作模式 SELinux 是透過 MAC 的方式來控管程序,他控制的主體是程序, 而目標則是該程序能否讀取的『檔案資源』!所以先來說明一下這些咚咚的相關性啦! · 主體 (Subject):SELinux 主要想要管理的就是程序,因此你可以將『主體』跟本章談到的 process 劃上等號; · 目標 (Object):主體程序能否存取的『目標資源』一般就是檔案系統。因此這個目標專案可以等檔案系統劃上等號; · 政策 (Policy):由於程序與檔案數量龐大,因此 SELinux 會依據某些服務來制訂基本的存取安全性政策。這些政策內還會有詳細的規則 (rule) 來指定不同的服務開放某些資源的存取與否。在目前的 CentOS 7.x 裡面僅有提供三個主要的政策,分別是: o targeted:針對網路服務限制較多,針對本機限制較少,是預設的政策; o minimum:由 target 修訂而來,僅針對選擇的程序來保護! o mls:完整的 SELinux 限制,限制方面較為嚴格。 建議使用預設的 targeted 政策即可。 · 安全性本文 (security context):我們剛剛談到了主體、目標與政策面,但是主體能不能存取目標除了政策指定之外,主體與目標的安全性本文必須一致才能夠順利存取。這個安全性本文 (security context) 有點類似檔案系統的 rwx 啦!安全性本文的內容與設定是非常重要的! 如果設定錯誤,你的某些服務(主體程序)就無法存取檔案系統(目標資源),當然就會一直出現『許可權不符』的錯誤訊息了!

上圖的重點在『主體』如何取得『目標』的資源訪問許可權! 由上圖我們可以發現,(1)主體程序必須要通過 SELinux 政策內的規則放行後,就可以與目標資源進行安全性本文的比對, (2)若比對失敗則無法存取目標,若比對成功則可以開始存取目標。問題是,最終能否存取目標還是與檔案系統的 rwx 許可權設定有關

<1>安全性文字(security context)

centos 7.x的target政策制定了非常多的規則,因此,只需要知道如何開啟/關閉某項規則放行即可。安全性文字是放置在inode中國的,主體想要讀取目標檔案資源時,需要讀取inode,在inode內就可以比對安全性文字以及rwx許可權是否正確,從而給予適當的讀取許可權依據

· 身份識別 (Identify):相當於賬號方面的身份識別!主要的身份識別常見有底下幾種常見的型別: o unconfined_u:不受限的使用者,也就是說,該檔案來自於不受限的程序所產生的!一般來說,我們使用可登入賬號來取得 bash 之後, 預設的 bash 環境是不受 SELinux 管制的~因為 bash 並不是什麼特別的網路服務!因此,在這個不受 SELinux 所限制的 bash 程序所產生的檔案,其身份識別大多就是 unconfined_u 這個『不受限』使用者囉! o system_u:系統使用者,大部分就是系統自己產生的檔案囉! 基本上,如果是系統或軟體本身所提供的檔案,大多就是 system_u 這個身份名稱,而如果是我們使用者透過 bash 自己建立的檔案,大多則是不受限的 unconfined_u 身份~如果是網路服務所產生的檔案,或者是系統服務運作過程產生的檔案,則大部分的識別就會是 system_u 囉!因為鳥哥這邊教大家使用文字介面來產生許多的資料,因此你看上面的三個檔案中,系統安裝主動產生的 anaconda-ks.cfs 及 initial-setup-ks.cfg 就會是 system_u,而我們自己從網路上面抓下來的 regular_express.txt 就會是 unconfined_u 這個識別啊! · 角色 (Role):透過角色欄位,我們可以知道這個資料是屬於程序、檔案資源還是代表使用者。一般的角色有: o object_r:代表的是檔案或目錄等檔案資源,這應該是最常見的囉; o system_r:代表的就是程序啦!不過,一般使用者也會被指定成為 system_r 喔! 你也會發現角色的欄位最後面使用『 _r 』來結尾!因為是 role 的意思嘛! · 型別 (Type) (最重要!):在預設的 targeted 政策中, Identify 與 Role 欄位基本上是不重要的!重要的在於這個型別(type) 欄位! 基本上,一個主體程序能不能讀取到這個檔案資源,與型別欄位有關!而型別欄位在檔案與程序的定義不太相同,分別是: o type:在檔案資源 (Object) 上面稱為型別 (Type); o domain:在主體程序 (Subject) 則稱為領域 (domain) 了!domain 需要與 type 搭配,則該程序才能夠順利的讀取檔案資源啦!

<2>程序與檔案SELinux type欄位的相關性

命令:$  ps -eZ     #觀察系統程序的SELinux的相關資訊

顯示的內容在target政策的對應如下

身份識別  角色 該對應在 targeted 的意義
unconfined_u  unconfined_r 一般可登入使用者的程序囉!比較沒有受限的程序之意!大多數都是使用者已經順利登入系統 (不論是網路還是本機登入來取得可用的 shell) 後, 所用來作業系統的程序!如 bash, X window 相關軟體等。
system_u  system_r 由於為系統賬號,因此是非交談式的系統運作程序,大多數的系統程序均是這種型別!

 但就如上所述,在預設的 target 政策下,其實最重要的欄位是型別欄位 (type), 主體與目標之間是否具有可以讀寫的許可權,與程序的 domain 及檔案的 type 有關!這兩者的關係我們可以使用 crond 以及他的配置檔案來說明! 亦即是 /usr/sbin/crond, /etc/crontab, /etc/cron.d 等檔案來說明。 

當我們執行 /usr/sbin/crond 之後,這個程式變成的程序的 domain 型別會是 crond_t 這一個~而這個 crond_t 能夠讀取的配置檔案則為 system_cron_spool_t 這種的型別。因此不論 /etc/crontab, /etc/cron.d  以及 /var/spool/cron 都會是相關的 SELinux 型別 (/var/spool/cron 為 user_cron_spool_t)。 文字看起 來不太容易瞭解,我們使用圖示來說明這幾個東西的關係!

(1) 首先,我們觸發一個可執行的目標檔案,那就是具有 crond_exec_t 這個型別的 /usr/sbin/crond 檔案; (2) 該檔案的型別會讓這個檔案所造成的主體程序 (Subject) 具有 crond 這個領域 (domain), 我們的政策針對這個領域已經制定了許多規則,其中包括這個領域可以讀取的目標資源型別; (3)檔案放到 /etc/cron.d/ 目錄下,就能夠被 crond 那支程序所讀取了; (4) 但最終能不能讀到正確的資料,還得要看 rwx 是否符合 Linux 許可權的規範!

3、SELinux三種模式的啟動、關閉與觀察

並非所有的Linux系統都支援SELinux,首先你需要先觀察一下你的Linux系統是否支援,對於centos7.x都支援SELinux。

目前SELinux依據啟動與否共有三種模式

· enforcing:強制模式,代表 SELinux 運作中,且已經正確的開始限制 domain/type 了; · permissive:寬容模式:代表 SELinux 運作中,不過僅會有警告訊息並不會實際限制 domain/type 的存取。這種模式可以運來作為 SELinux 的 debug 之用; · disabled:關閉,SELinux 並沒有實際運作。

如果是 Disabled 的模式,那麼 SELinux 將不會運作,當然受限的程序也不會經過 SELinux , 也是直接去判斷 rwx 而已。那如果是寬容 (permissive) 模式呢?這種模式也是不會將主體程序抵擋 (所以箭頭是可以直接穿透的喔!),不過萬一沒有通過政策規則,或者是安全本文的比對時, 那麼該讀寫動作將會被紀錄起來 (log),可作為未來檢查問題的判斷依據。至於最終那個 Enforcing 模式,就是實際將受限主體進入規則比對、安全本文比對的流程,若失敗,就直接抵擋主體程序的讀寫行為,並且將他記錄下來。 如果通通沒問題,這才進入到 rwx 許可權的判斷。

查詢目前的SELinux模式:命令:$  getenforce

查詢SELinux的政策:

[[email protected] ~]# sestatus [-vb]
選項與引數:
-v :檢查列於 /etc/sestatus.conf 內的檔案與程序的安全性本文內容;
-b :將目前政策的規則布林值列出,亦即某些規則 (rule) 是否要啟動 (0/1) 之意;
範例一:列出目前的 SELinux 使用哪個政策 (Policy)?
[[email protected] ~]# sestatus
SELinux status: enabled                 <==是否啟動 SELinux
SELinuxfs mount: /sys/fs/selinux        <==SELinux 的相關檔案資料掛載點
SELinux root directory: /etc/selinux    <==SELinux 的根目錄所在
Loaded policy name: targeted            <==目前的政策為何?
Current mode: enforcing                 <==目前的模式
Mode from config file: enforcing        <==目前配置檔案內規範的 SELinux 模式
Policy MLS status: enabled              <==是否含有 MLS 的模式機制
Policy deny_unknown status: allowed     <==是否預設抵擋未知的主體程序
Max kernel policy version: 28 
如上所示,目前是啟動的,而且是 Enforcing 模式,而由配置檔案查詢得知亦為 Enforcing 模式。 此
外,目前的預設政策為 targeted 這一個。SELinux 的配置檔案是/etc/selinux/config 
[[email protected] ~]# vim /etc/selinux/config
SELINUX=enforcing                       <==調整 enforcing|disabled|permissive
SELINUXTYPE=targeted                    <==目前僅有 targeted, mls, minimum 三種政策

<1>SELinux的啟動與關閉

如果改變政策則需要重新啟動,如果已經在Enforcing的模式下,但是可能由於一些設定的導致SELinux讓某些服務無法正常運作,此時你可以將Enforcing的模式改為寬容模式,讓SELinux只會警告無法順利聯機的訊息,而不是直接抵擋主體程序的讀取許可權,讓SELinux模式在Enforcing與permissive之間切換的方法為:

命令:$  setenforce  [0|1]    #其中0代表轉化成peimissive寬容模式;1代表轉成Enforcing強制模式

4、SELinux政策內的規則管理

<1>SELinux各個規則的布林值查詢getsebool

[[email protected] ~]# getsebool [-a] [規則的名稱]
選項與引數:
-a :列出目前系統上面的所有 SELinux 規則的布林值為開啟或關閉值

或者使用命令:$  sestatus -b

<2>SELinux各個規則規範的主題程序能夠讀取的檔案SELinux type查詢seinfo,sesearch

第一步:安裝seinfo工具

第二步:

[[email protected] ~]# seinfo [-Atrub]
選項與引數:
-A :列出 SELinux 的狀態、規則布林值、身份識別、角色、類別等所有資訊
-u :列出 SELinux 的所有身份識別 (user) 種類
-r :列出 SELinux 的所有角色 (role) 種類
-t :列出 SELinux 的所有類別 (type) 種類
-b :列出所有規則的種類 (布林值)
[[email protected] ~]# sesearch [-A] [-s 主體類別] [-t 目標類別] [-b 布林值]
選項與引數:
-A :列出後面資料中,允許『讀取或放行』的相關資料
-t :後面還要接類別,例如 -t httpd_t
-b :後面還要接 SELinux 的規則,例如 -b httpd_enable_ftp_server

<3>修改SELinux規則的布林值setsebool

[[email protected] ~]# setsebool [-P] 『規則名稱』 [0|1]
選項與引數:
-P :直接將設定值寫入配置檔案,該設定資料未來會生效的!
範例一:查詢 httpd_enable_homedirs 這個規則的狀態,並且修改這個規則成為不同的布林值
[[email protected] ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off <==結果是 off ,依題意給他啟動看看!
[[email protected] ~]# setsebool -P httpd_enable_homedirs 1 # 會跑很久很久!請耐心等待!
[[email protected] ~]# getsebool httpd_enable_homedirs
httpd_enable_homedirs --> on

5、SELinux安全文字的修改

<1> 使用 chcon 手動修改檔案的 SELinux type

[[email protected] ~]# chcon [-R] [-t type] [-u user] [-r role] 檔案
[[email protected] ~]# chcon [-R] --reference=範例檔案 檔案
選項與引數:
-R :連同該目錄下的次目錄也同時修改;
-t :後面接安全性本文的型別欄位!例如 httpd_sys_content_t ;
-u :後面接身份識別,例如 system_u; (不重要)
-r :後面街角色,例如 system_r; (不重要)
-v :若有變化成功,請將變動的結果列出來
--reference=範例檔案:拿某個檔案當範例來修改後續接的檔案的型別!
範例一:查詢一下 /etc/hosts 的 SELinux type,並將該型別套用到 /etc/cron.d/checktime 上
[[email protected] ~]# ll -Z /etc/hosts
-rw-r--r--. root root system_u:object_r:net_conf_t:s0 /etc/hosts
[[email protected] ~]# chcon -v -t net_conf_t /etc/cron.d/checktime
changing security context of ‘/etc/cron.d/checktime’
[[email protected] ~]# ll -Z /etc/cron.d/checktime
-rw-r--r--. root root unconfined_u:object_r:net_conf_t:s0 /etc/cron.d/checktime
範例二:直接以 /etc/shadow SELinux type 套用到 /etc/cron.d/checktime 上!
[[email protected] ~]# chcon -v --reference=/etc/shadow /etc/cron.d/checktime
[[email protected] ~]# ll -Z /etc/shadow /etc/cron.d/checktime
-rw-r--r--. root root system_u:object_r:shadow_t:s0 /etc/cron.d/checktime
----------. root root system_u:object_r:shadow_t:s0 /etc/shadow

上面的練習『都沒有正確的解答!』因為正確的 SELinux type 應該就是要以 /etc/cron.d/ 底下的檔案 為標準來處理,讓 SELinux 自己解決預設目錄下的 SELinux type 用 restorecon <2>使用 restorecon 讓檔案恢復正確的 SELinux type

[[email protected] ~]# restorecon [-Rv] 檔案或目錄
選項與引數:
-R :連同次目錄一起修改;
-v :將過程顯示到螢幕上
範例三:將 /etc/cron.d/ 底下的檔案通通恢復成預設的 SELinux type!
[[email protected] ~]# restorecon -Rv /etc/cron.d
restorecon reset /etc/cron.d/checktime context system_u:object_r:shadow_t:s0->
system_u:object_r:system_cron_spool_t:s0
# 上面這兩行其實是同一行喔!表示將 checktime 由 shadow_t 改為 system_cron_spool_t
範例四:重新啟動 crond 看看有沒有正確啟動 checktime 囉!?
[[email protected] ~]# systemctl restart crond
[[email protected] ~]# tail /var/log/cron
# 再去瞧瞧這個 /var/log/cron 的內容,應該就沒有錯誤訊息了

<3>semanage 預設目錄的安全性本文查詢與修改 為什麼 restorecon 可以『恢復』原本的 SELinux type 呢?那肯定就是有個地方在紀錄每個檔案/目錄的 SELinux 預設型別囉? 沒錯!是這樣~那要如何 (1)查詢預設的 SELinux type 以及 (2)如何增加/修改/刪除預設的 SELinux type 呢?很簡單~透過 semanage 即可!他是這樣使用的:  

[[email protected] ~]# semanage {login|user|port|interface|fcontext|translation} -l
[[email protected] ~]# semanage fcontext -{a|d|m} [-frst] file_spec
選項與引數:
fcontext :主要用在安全性本文方面的用途, -l 為查詢的意思;
-a :增加的意思,你可以增加一些目錄的預設安全性本文型別設定;
-m :修改的意思;
-d :刪除的意思。
範例一:查詢一下 /etc /etc/cron.d 的預設 SELinux type 為何?
[[email protected] ~]# semanage fcontext -l | grep -E '^/etc |^/etc/cron'
SELinux fcontext type Context
/etc all files system_u:object_r:etc_t:s0
/etc/cron\.d(/.*)? all files system_u:object_r:system_cron_spool_t:s0

6、一個網路服務案例及登入檔案協助

詳情見書P749-758