SELinux旅程Part4-稽核 SELinux 事件(Auditing SELinux Event)

先附上自製影片, 之後會再持續更新哦!
用 Ubuntu PPA 開啟 SELinux 且運行在 enforcing mode[Youtube]: 
https://www.youtube.com/watch?v=4fdXuIIBxes
Ubuntu PPA(Personal Package Archives)可以讓我們自行製作 Package 並透過 apt 套件管理工具下載。有鑒於社群最近修掉了一個 issue,此 PPA 未來會再進行更新,到時候就不必修改核心(Kernel)囉。

前言

在上一篇 SELinux旅程Part3-SELinux存取控制設計中,我們了解到 SELinux 的設計理念如何對應到存取控制的核心概念(i.e. Subject、Action、Object),如何利用標籤(或稱為安全性文本(Security Context))與政策(Policy)中的規則,來規範存取主體的存取範圍。 
這篇緊接著分享,當核心檢查存取權限或是改變 SELinux 模式等等,Linux Audit System 都會把這些事件紀錄起來,此行為稱作稽核 SELinux 事件(Auditing SELinux Event)。
這些稽核訊息(Audit Message)不外乎可以幫助我們進行除錯和確認系統運行狀態,更進一步,還可以利用如 audit2allow 程式幫助我們把稽核訊息轉換成政策規則。

稽核 SELinux 事件

SELinux 事件分為兩大類,可以參考官方的 wiki。:
  1. 存取向量快取事件(AVC Audit Events):
    當存取行為發生時,核心會去檢查存取主體是否有權限去存取資源,檢查結果會被儲存在存取向量快取(Access Vector Cache)中,接著核心會根據設定配合 Linux Audit System 來紀錄檢查訊息。 常見情況為紀錄存取否決(Access Deny)的結果,也可以要求紀錄存取成功的訊息(在政策中使用 auditallow 規則)。
  2. 一般的 SELinux 稽核事件(General SELinux Audit Events):
    諸如 SELinux 系統錯誤、初始化、政策(Policy)載入、更改 SELinux 模式、改變布林值(Boolean)或是重新上標籤等等皆包含在此類中。

存取向量快取事件(AVC Audit Events)

此事件是當 Access Deny 或特別要求要有稽核訊息(使用 auditallow 規則)時才會發生。 這邊帶讀者了解一下存取向量快取事件的訊息格式,不了解事件訊息的內容是無法除錯的呦!
因為使用 Linux Audit System,基本上格式的欄位名稱是依照 Linux Audit System 所提供的欄位名稱為主,在此事件訊息中預設會出現的格式欄位為 type、msg、avc、scontext、tcontext、tclass,其他的欄位依照不同存取情況出現,可能有 pid、capability、file name、device、ip address 等等。 透過整合欄位的內容我們可以知道發生什麼情況,並且該如何處理。
  • type: 此事件可能的值有 AVC、USER_AVC、SYSCALL
    • AVC: 代表此事件為核心中的 AVC 事件。
    • USER_AVC: 使用者空間(User Space)中的 AVC 事件。 SELinux 世界中,我們可以在程式裡利用 SELinux API 來對自己的資源做存取檢查,例如 Database System,有此行為的程式被稱作使用者空間的資源管理者(User-space Object Manager),我們之後會特別寫一篇來分享。
    • SYSCALL: 代表與此 AVC 事件相關的 System Call,為事件做額外補充,如果 AVC 事件的 serial number 和此 SYSCALL 訊息的 serial number 一樣,例 msg=audit(time:serial_number),則代表同一個事件。
  • msg: 如上所述一個 audit 字串後面接了一串識別號碼。
  • avc: 分別有 denied 和 granted 兩種結果,其中 granted 代表使用 auditallow 規則且存取成功。
  • scontext: 來源(Source),通常是存取主體(Subject),的安全性文本(Security Context)/標籤(Label)。
  • tcontext: 資源(Object)/目標(Target)的安全性文本(Security Context)/標籤(Label)。
  • tclass: 資源的類別(Class)。
type=AVC msg=audit(1243332701.744:101): avc: denied
{ getattr } for pid=2714 comm="ls"
path="/usr/lib/locale/locale-archive" dev=dm-0 ino=353593
scontext=system_u:object_r:unlabeled_t:s0
tcontext=system_u:object_r:locale_t:s0 tclass=file

type=SYSCALL msg=audit(1243332701.744:101): arch=40000003
syscall=197 success=yes exit=0 a0=3 a1=553ac0 a2=552ff4
a3=bfc5eab0 items=0 ppid=2671 pid=2714 auid=0 uid=0 gid=0 euid=0
suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts1 ses=1 comm="ls"
exe="/bin/ls" subj=system_u:object_r:unlabeled_t:s0 key=(null)
從上面例子可看出,此事件發生在 ls 程序執行中,此程序對於 /usr/lib/locale/locale-archive 檔案(file)沒有 getattr 權限。
如果想要允許此存取行為該怎麼辦呢? 在政策中寫如下 allow 規則:
allow unlabeled_t locale_t:file { getattr };
重新載入政策後即可允許此存取行為。
這邊跟讀者做個提醒,在核心中檢查跟事件紀錄是分開的,且政策規則也會影響紀錄的行為,因此並不是所有的存取事件皆會被記錄下來,還是得看核心中的實作或政策撰寫情形。 舉個例子,如果在政策中使用 dontaudit 規則,則當有 Access Deny 事件發生時,標有 dontaudit 的存取事件不會被紀錄。

找尋 dontaudit 規則

sesearch --dontaudit
使用 sesearch 程式可以便利的搜尋此政策中的規則,透過 --dontaudit 選項可以列出所有標記為 dontaudit 的存取行為。
圖1. 列出 dontaudit 規則

一般的 SELinux 稽核事件(General SELinux Audit Events)

此事件預設出現的格式欄位為 type 和 msg,其他的欄位依照不同情形出現,實際的格式欄位和其內容需要參考 Linux Audit System 所提供的欄位資訊。 以下我們以舉例的方式,來看看有哪些一般的 SELinux 稽核事件吧!

政策載入

type=MAC_POLICY_LOAD msg=audit(1336662937.117:394): policy loaded auid=0 ses=2
type=SYSCALL msg=audit(1336662937.117:394): arch=c000003e syscall=1 success=yes
exit=4345108 a0=4 a1=7f0a0c547000 a2=424d14 a3=7fffe3450f20 items=0 ppid=3845
pid=3848 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts2
ses=2 comm="load_policy" exe="/sbin/load_policy"
subj=unconfined_u:unconfined_r:load_policy_t:s0-s0:c0.c1023 key=(null)
type=USER_MAC_POLICY_LOAD msg=audit(1336662938.535:395): pid=0 uid=0
auid=4294967295 ses=4294967295 subj=system_u:system_r:xserver_t:s0-s0:c0.c1023
msg='avc: received policyload notice (seqno=2) : exe="/usr/bin/Xorg" sauid=0
hostname=? addr=? terminal=?'
當政策載入時,核心中 MAC_POLICY_LOAD 稽核事件產生,如果使用者空間中的資源管理者(User-space Object Manager)偵測到此事件發生且作出對應行為時,資源管理者會產生 USER_MAC_POLICY_LOAD 稽核事件。

改變 SELinux 模式

如下所述,使用 setenforce 來改變 SELinux 模式時,產生 MAC_STATUS 稽核事件。
type=MAC_STATUS msg=audit(1336836093.835:406): enforcing=1 old_enforcing=0
auid=0 ses=2
type=SYSCALL msg=audit(1336836093.835:406): arch=c000003e syscall=1 success=yes
exit=1 a0=3 a1=7fffe743f9e0 a2=1 a3=0 items=0 ppid=2047 pid=5591 auid=0 uid=0
gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=2
comm="setenforce" exe="/usr/sbin/setenforce"
subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)

改變 SELinux 布林(Boolean)值

type=MAC_CONFIG_CHANGE msg=audit(1336665376.629:423):
bool=domain_paste_after_confirm_allowed val=0 old_val=1 auid=0 ses=2
type=SYSCALL msg=audit(1336665376.629:423): arch=c000003e syscall=1 success=yes
exit=2 a0=3 a1=7fff42803200 a2=2 a3=7fff42803f80 items=0 ppid=2015 pid=4664
auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=2
comm="setsebool" exe="/usr/sbin/setsebool"
subj=unconfined_u:unconfined_r:setsebool_t:s0-s0:c0.c1023 key=(null)
從上面可看出,使用 setsebool 來改變 SELinux 布林值,產生 MAC_CONFIG_CHANGE 稽核事件。

利用 audit2allow 產生政策

如果要將訊息一一看過並轉換成政策規則,這未免也太麻煩。 因此可以使用 audit2allow 工具,來幫您把稽核訊息轉換成政策規則,接著再一條一條去檢視規則。
cat /var/log/audit/audit.log | audit2allow -M test
執行上面的指令後會產生 test.te 和 test.pp 兩個檔案,test.te 中的內容即為稽核訊息所轉換成的政策規則,test.pp 為模組化的政策(Modular Policy)檔案,一般來說需要將 test.te 變成 test.pp 才可使用,此 audit2allow 已幫您做完此步驟,接下來可以透過如下指令載入此政策檔案。
semodule -i test.pp
載入後即可允許 test.te 中所標示的規則權限。

訊息記錄檔

看完訊息的格式後我們來了解一下,這些訊息都被記錄在何處呢? Linux Audit System 中的 Audit Daemon 運行起來之前,稽核訊息會被記錄在核心 Log(/var/log/dmesg)中,或是被記錄在系統 Log(/var/log/messages)中。 Audit Daemon 運行起來後預設會被記錄在 /var/log/audit/audit.log 中,這位置沒有一定,主要還是看管理者如何透過設定檔去設定 Linux Audit System。

Linux Audit System

第二篇有提到過,核心中要開啟 SELinux 功能前需要先開啟 Audit 功能才行。
Linux Audit System 分為核心跟使用者空間的部分,設計理念是將系統行為劃分為許多的稽核事件,透過追蹤系統呼叫(System Call)紀錄 "誰" 對 "某個對象" 做了什麼事情。 使用者空間程式由 Red Hat 開發,系統管理員可以設計稽核規則(audit.rules)去選擇想監看的系統行為,透過連接稽核事件來幫助釐清系統安全問題、資源使用問題或是效能問題,規則主要分為三大類 Control、File System 和 System Call,管理員利用 auditctl 來做規則設定並將其載入核心。
因為實作的關係,預設會稽核 SELinux 事件並不需要設定稽核規則,但要注意的是 Linux Audit System 會因為訊息產生的速度(messages/sec)和量受影響,如果速度太快超過訊息產生的速度限制或是量太多超過 Buffer 大小則訊息會被丟棄。 使用以下指令來查看 Linux Audit System 的狀態,其中 lost 欄位代表被丟棄的訊息。
auditctl -s
為了防止訊息被丟棄,我們利用 auditctl 設定 Control 規則來調整 Buffer 大小以及調整訊息產生的速度限制。
auditctl -b 8192 -r 0
-b 選項可以擴大 Audit Buffer,-r 可以調整速度標準,0 代表沒限制。 
auditd 服務未運行的狀態下,audit 訊息會被記錄至核心 Log 中,但因為核心 Log 也有訊息產生的速度限制,我們可以透過 sysctl 來進行設定。
sysctl -w kernel.printk_ratelimit=0
一樣把速度限制關掉,如此一來就能夠盡量不遺漏訊息,幫助我們更加掌握系統裡面發生的事件。
Linux Audit System 整體架構如圖二,當應用程式運行導致系統行為發生時 Linux Audit System 會將其依照稽核規則記錄下來並且利用 Netlink IPC 將訊息從核心的 Audit Buffer 傳遞到使用者空間中的 auditd 服務,依照管理者的設定(auditd.conf),auditd 可以將接收到的訊息寫入 audit.log 檔案中或是利用 audispd 來轉接到其他工具(例如 syslog)亦或是傳遞至遠端機器(audisp-remote),如果沒有運行 auditd 服務則稽核訊息預設紀錄在核心 log(/var/log/dmesg)中。
audit.log 中紀錄的訊息比較複雜且未經過整理,我們可以透過 aureport 來整理出更好看懂的訊息,也可以透過 ausearch 來尋找 audit.log 中特定的訊息。
圖2. Linux 稽核系統架構
(Ref:https://wiki.itcollege.ee/index.php/Auditd#cite_note-1)

總結

這次我們了解到 SELinux 如何搭配 Linux Audit System 來稽核 SELinux 事件,透過稽核 SELinux 事件我們能驗證所撰寫的政策是否有正常的在發揮功效。 預設上,如果有打開核心 Audit 功能,就算沒有使用者空間中的 auditd 服務來接收訊息SELinux 事件訊息還是會產生,只是它會被記錄在核心 log 檔案中。 我們希望盡量接收到所有訊息,但核心中實作、政策中的 dontaudit 規則、Audit Buffer 大小和訊息產生速度限制皆會影響訊息產生,系統管理員務必小心。

參考連結:

  1. https://selinuxproject.org/page/NB_AL
  2. https://github.com/linux-audit
  3. http://man7.org/linux/man-pages/man8/auditd.8.html
  4. https://people.redhat.com/sgrubb/audit/index.html
  5. https://github.com/linux-audit/audit-documentation/wiki/SPEC-Writing-Good-Events
  6. https://wiki.itcollege.ee/index.php/Auditd#cite_note-1
  7. https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/chap-system_auditing

留言