理解Linux下的SELinux

理解Linux下的SELinux

長久以來,每當遇到授權問題或者新安裝的主機,我的第一反應是通過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

<code>~]#

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

/<code>

顯示文件的Context信息

<code>~]#

ls

-Z

system_u

:object_r

:admin_home_t

:s0

anaconda-ks

.cfg

/<code>

臨時修改文件的SELinux Type 為htttpd_sys_content_t

<code>~]/<code>

SELinux 的運行狀態

SELinux 有三個運行狀態,分別是disabled, permissive 和 enforcing

Disable: 禁用SELinux,不會給任何新資源打Label,如果重新啟用的話,將會給資源重新打上Lable,過程會比較緩慢。Permissive:如果違反安全策略,並不會真正的執行拒絕操作,替代的方式是記錄一條log信息。Enforcing: 默認模式,SELinux的正常狀態,會實際禁用違反策略的操作

查看當前的運行狀態

<code>~] Enforcing/<code>

臨時改變運行狀態為Permissive

<code>~] ~] Permissive/<code>

臨時改變運行狀態為 Enforcing

<code>~] ~] Enforcing/<code>

使用sestatus可以查看完整的狀態信息

<code>

~]#

sestatus

SELinux status:

enabled

SELinuxfs mount:

/sys/fs/selinux

SELinux root directory:

/etc/selinux

Loaded policy name:

targeted

Current mode:

enforcing

Mode from config file:

enforcing

Policy MLS status:

enabled

Policy deny_unknown status:

allowed

Max kernel policy version:

30

/<code>

SELinux Log

SELinux 的Log日誌默認記錄在/var/log/audit/audit.log

<code>~]# 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/<code>

/var/log/message 也會記錄相應的信息,例如:

<code>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

-

466

d-a606-

92

c9f40d316d/<code>

SELinux 配置文件

SELinux的配置文件位於/etc/selinux/config。默認配置文件主要兩部分,一個是SELinux的運行狀態和SELinuxType。直接在配置文件中修改SELinux將會在下次啟動時生效。

<code>

SELINUX

=enforcing

SELINUXTYPE

=targeted/<code>

SELinux Booleans

Booleans允許在運行時修改SELinux安全策略。

列出所有的Booleans選項

<code>~] SELinux boolean State Default Description smartmon_3ware (

off

,

off

) Determine whether smartmon can... mpd_enable_homedirs (

off

,

off

) Determine whether mpd can traverse.../<code>

臨時修改httpd_can_network_connect_db狀態為開啟

<code>~]/<code>

深入研究

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