長久以來,每當遇到授權問題或者新安裝的主機,我的第一反應是通過setenforce 0命令禁用SElinux,來減少產生的權限問題,但是這并不是一個良好的習慣。這篇文章嘗試對SELinux的基本概念和用法進行簡單介紹,并且提供一些更深入的資料。
Linux下默認的接入控制是DAC,其特點是資源的擁有者可以對它進行任何操作(讀、寫、執行)。當一個進程準備操作資源時,Linux內核會比較進程和資源的UID和GID,如果權限允許,就可以進行相應的操作。此種方式往往會帶來一些問題,如果一個進程是以root的身份運行,也就意味著他能夠對系統的任何資源進行操作,而且不被限制。 假如我們的軟件存在漏洞呢?這個往往是一個災難性的問題。因此,就引出了另外的一種安全接入控制機制mac,Linux下的一種現實是SELinux,也就是我們將要討論的內容。
基本概念
Mandatory Access Control (MAC)
SELinux 屬于MAC的具體實現,增強了Linux系統的安全性。MAC機制的特點在于,資源的擁有者,并不能決定誰可以接入到資源。具體決定是否可以接入到資源,是基于安全策略。而安全策略則是有一系列的接入規則組成,并僅有特定權限的用戶有權限操作安全策略。
一個簡單的例子,則是一個程序如果要寫入某個目錄下的文件,在寫入之前,一個特定的系統代碼,將會依據進程的Context和資源的Context查詢安全策略,并且根據安全策略決定是否允許寫入文件。
Flask Security Architecture
SELinux的軟件設計架構是參照Flask,Flask是一種靈活的操作系統安全架構,并且在Fluke research operating system中得到了實現。Flask的主要特點是把安全策略執行代碼和安全策略決策代碼,劃分成了兩個組件。安全策略決策代碼在Flask架構中稱作Security Server。除了這兩個組件以外,另外一個組件Vector Cache(AVC), 主要提供策略決策結果的緩存,以此提高Security Server的性能。其具體執行流程為,安全策略執行代碼通過AVC查詢Security Server的安全策略決策結果,并將其緩存以備下次使用。
The Flask Security Architecture: System Support for Diverse Security Policies
Linux Security Module
前面兩部分介紹了MAC機制和Flask架構,最終SELinux的實現是依賴于Linux提供的Linux Security Module框架簡稱為LSM。其實LSM的名字并不是特別準確,因為他并不是Linux模塊,而是一些列的hook,同樣也不提供任何的安全機制。LSM的的重要目標是提供對linux接入控制模塊的支持。
Linux Security Module Framework
LSM 在內核數據結構中增加了安全字段,并且在重要的內核代碼(系統調用)中增加了hook。可以在hook中注冊回調函數對安全字段進行管理,以及執行接入控制。
SELinux
Security Enhanced Linux(SELinux) 為Linux 提供了一種增強的安全機制,其本質就是回答了一個“Subject是否可以對Object做Action?”的問題,例如 Web服務可以寫入到用戶目錄下面的文件嗎?其中Web服務就是Subject而文件就是Object,寫入對應的就是Action。
依照上面的例子,我們引入了幾個概念,分別是Subject、Object、Action、以及例子沒有體現出來的Context:
- Subject: 在SELinux里指的就是進程,也就是操作的主體。
- Object: 操作的目標對象,例如 文件
- Action: 對Object做的動作,例如 讀取、寫入或者執行等等
- Context: Subject和Object都有屬于自己的Context,也可以稱作為Label。Context有幾個部分組成,分別是SELinux User、SELinux Role、SELinux Type、SELinux Level,每個部分的具體含義,將在下一章介紹。
用戶程序執行的系統調用(例如讀取文件),都要被SELinux依據安全策略進行檢查。如果安全策略允許操作,則繼續,否則將會拋出錯誤信息給應用程序。SELinux決策的同時還需要Subject和Object的Context信息,確定所屬的User、Role和Type等信息,以此查詢對應的安全策略進行決策。SELinux同樣也使用了AVC機制用于緩存決策結果,以此來提高性能。
SELinux Context
進程和文件都有屬于自己的Context信息,Context分為幾個部分,分別是 SELinux User、Role、Type 和一個可選的Level信息。SELinux在運行過程中將使用這些信息查詢安全策略進行決策。
- SELinux User:每一個Linux用戶都會映射到SELinux用戶,每一個SELinux User都會對應相應的Role。
- SELinux Role:每個Role也對應幾種SELinux Type,并且充當了User和Type的‘中間人’
- SELinux Type:安全策略使用SELinux Type制定規則,定義何種Domian(Type)的Subject,可以接入何種Type的Object。
顯示進程的Context
~]# ps -Z
LABEL PID TTY TIME CMD
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 9509 pts/1 00:00:00 sudo
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 9515 pts/1 00:00:00 su
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 9516 pts/1 00:00:00 bash
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 9544 pts/1 00:00:00 ps
顯示文件的Context信息
~]# ls -Z
system_u:object_r:admin_home_t:s0 anaconda-ks.cfg
臨時修改文件的SELinux Type 為htttpd_sys_content_t
~]# chcon -t httpd_sys_content_t file-name
SELinux 的運行狀態
SELinux 有三個運行狀態,分別是disabled, permissive 和 enforcing
- Disable: 禁用SELinux,不會給任何新資源打Label,如果重新啟用的話,將會給資源重新打上Lable,過程會比較緩慢。
- Permissive:如果違反安全策略,并不會真正的執行拒絕操作,替代的方式是記錄一條log信息。
- Enforcing: 默認模式,SELinux的正常狀態,會實際禁用違反策略的操作
查看當前的運行狀態
~]# getenforce
Enforcing
臨時改變運行狀態為Permissive
~]# setenforce 0
~]# getenforce
Permissive
臨時改變運行狀態為 Enforcing
~]# setenforce 1
~]# getenforce
Enforcing
使用sestatus可以查看完整的狀態信息
~]# sestatus
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinuxSELinux root directory: /etc/selinuxLoaded policy name: targetedCurrent mode: enforcingMode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 30
SELinux Log
SELinux 的Log日志默認記錄在/var/log/audit/audit.log
~]# cat /var/log/audit/audit.log
type=AVC msg=audit(1223024155.684:49): avc: denied { getattr } for pid=2000 comm="httpd" path="/var/www/html/file1" dev=dm-0 ino=399185 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=system_u:object_r:samba_share_t:s0 tclass=file
/var/log/message 也會記錄相應的信息,例如:
May 7 18:55:56 localhost setroubleshoot: SELinux is preventing httpd (httpd_t) "getattr" to /var/www/html/file1 (samba_share_t). For complete SELinux messages. run sealert -l de7e30d6-5488-466d-a606-92c9f40d316d
SELinux 配置文件
SELinux的配置文件位于/etc/selinux/config。默認配置文件主要兩部分,一個是SELinux的運行狀態和SELinuxType。直接在配置文件中修改SELinux將會在下次啟動時生效。
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
SELinux Booleans
Booleans允許在運行時修改SELinux安全策略。
列出所有的Booleans選項
~]# semanage boolean -l
SELinux boolean State Default Description
smartmon_3ware (off , off) Determine whether smartmon can...
mpd_enable_homedirs (off , off) Determine whether mpd can traverse...
臨時修改httpd_can_network_connect_db狀態為開啟
~]# setsebool httpd_can_network_connect_db on
深入研究
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html-single/selinux_users_and_administrators_guide/index#chap-Security-Enhanced_Linux-Working_with_SELinux
http://www.kroah.com/linux/talks/ols_2002_lsm_paper/lsm.pdf
https://www.cs.cmu.edu/~dga/papers/flask-usenixsec99.pdf
https://people.redhat.com/duffy/selinux/selinux-coloring-book_A4-Stapled.pdf