跳至內容
出自 Arch Linux 中文维基

AppArmor 是一種強制訪問控制(Mandatory Access Control, MAC)系統,基於 Linux 安全模塊(Linux Security Modules, LSM)實現。

就像其他大多數的 Linux 安全模塊一樣,AppArmor 是對默認的的自主訪問控制(Discretionary Access Control, DAC)的補充,而非替代。因此,程序通過 AppArmor 獲取到的權限不可能大於原本在 DAC 下擁有的權限。

Ubuntu,SUSE 和許多其他的發行版默認使用 AppArmor,而 RHEL(及其衍生發行版)所使用的 SELinux 需要特定的用戶空間工具才能正常使用。SELinux 通過附加標籤的方式管理所有的文件、進程和對象,因而十分靈活。不過,普遍認為 SELinux 難以配置,且需要支持擴展屬性的的文件系統才能運作。相反,AppArmor 基於文件路徑,配置文件也相對簡單易懂。

AppArmor 通過對特定應用執定專用的規則集,主動保護作業系統和應用程式免受來自內外部的威脅,包括部分零日漏洞攻擊。安全策略決定了每個應用所能夠訪問的系統資源及其權限。沒有在安全配置文件中允許的訪問,將被默認攔截。AppArmor 隨附了一些默認策略,再結合使用高級靜態分析與基於學習的工具,即使是極其複雜的應用程式,用戶也可以在數小時內完成其 AppArmor 策略的編寫。

任何違反策略的訪問都將在系統日誌中報告。也可以通過配置 AppArmor,令其在越權訪問發生時,在用戶桌面實時彈出警告通知。

安裝

AppArmor 可以在所有的官方支持的內核中使用。

安裝 apparmor 以獲取管理 AppArmor 的用戶空間工具與庫。要在啟動時加載所有 AppArmor 安全配置文件,啟用 apparmor.service

要在每次引導時將 AppArmor 作為默認的安全模型啟用,設置以下的內核參數

lsm=landlock,lockdown,yama,integrity,apparmor,bpf
注意:lsm= 內核參數決定了 Linux 安全模塊的初始化順序。內核已配置的 lsm= 值可以通過 zgrep CONFIG_LSM= /proc/config.gz 查看,當前值可以通過 cat /sys/kernel/security/lsm 查看。
  • 確保 apparmor 是參數列表中的第一個「主要」模塊。[1]合法的值和順序的樣例可以在 security/Kconfig 查看。
  • lsm= 中不應包含 capability,因為它始終會被自動隱式包含。

自定義內核

自行編譯內核時,需要啟用以下選項:

CONFIG_SECURITY_APPARMOR=y
CONFIG_AUDIT=y

要讓內核在無需設置內核參數的前提下默認啟用 AppArmor Linux 安全模型,需要額外添加 CONFIG_LSM 選項,並將 apparmor 設定為列表中的第一個「主要」模塊。

CONFIG_LSM="landlock,lockdown,yama,integrity,apparmor,bpf"

使用方法

顯示當前狀態

檢測 AppArmor 是否成功啟動:

$ aa-enabled
Yes

顯示當前運行狀態,執行 aa-status(8)

# aa-status
apparmor module is loaded.
44 profiles are loaded.
44 profiles are in enforce mode.
 ...
0 profiles are in complain mode.
0 processes have profiles defined.
0 processes are in enforce mode.
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.

complain 模式下,違反策略的訪問將被允許,但該行為會被記錄在日誌中。complain 模式常用於了解程序正常運行所需要的權限,或是測試新撰寫的配置文件是否合適。但是,需要注意的是,在配置文件中被設定為 deny 的規則在 complain 模式下仍然會強制執行。

enforce 模式下,違反策略的訪問將被拒絕,並記錄到日誌中。

解析配置文件

使用 apparmor_parser 以加載、卸載、重啟、緩存或是統計配置文件。默認行為(-a)是以 enforce 模式加載配置文件。要以 complain 模式加載,請使用 -C 參數。要覆蓋已有配置文件,使用 -r 參數。要刪除配置文件,使用 -R 參數。每次操作也可能應用到多個配置文件上。參見 apparmor_parser(8) 手冊頁面以了解詳情。

停用

要在當前會話臨時停用 AppArmor,執行以下命令以停用所有配置文件:

# aa-teardown 

要永久停用 AppArmor 配置文件,請停用 apparmor.service。要阻止內核加載 AppArmor,刪除在安裝 AppArmor 時添加的 lsm= 內核參數

配置

審計與生成配置文件

要創建新的配置文件,確保 Audit 框架英語Audit framework正在運行,因為 Arch Linux 使用 systemd,內核日誌默認不會保存到文件中。AppArmor 可以從用戶空間的 auditd 進程抓取內核日誌,從而協助編寫配置文件。

注意:AppArmor audit 消息使用 AVC 記錄格式,使用 ausearch 搜索時可能破壞 audit 日誌的解析。在此查看漏洞報告:[2][3][4]

可以使用 aa-genprof(8)aa-autodep(8) 創建新的 AppArmor 配置文件。新創建的配置文件默認處於 complain 模式:此模式下,違反規則的行為僅會被記錄,不會被拒絕。要交互式地創建配置文件,可以使用 apparmor 包中的 aa-logprof(8)。配置完成後,請使用 aa-enforce(8) 將配置文件設置為 enforce 模式。此模式下,配置文件中的規則將被嚴格執行。此外,可以重複執行 aa-logprof(8) 以添加額外的規則,也可以使用 aa-complain(8) 將配置文件重新設置為 complain 模式。可以在此找到更為詳細的教程:AppArmor wiki - Profiling with tools

需要注意的是,aa-logprof(8) 也提供 deny 規則。不過根據 AppArmor 的設計邏輯,除非規則明確允許,否則任何行為都將被拒絕,因此嚴格來說沒有必要使用 deny 規則。不過,deny 規則有以下兩個用途:

  1. deny 規則的優先級比 allow 規則更高,在 /etc/apparmor.d/abstractions 中的許多 abstraction 中都有使用,用來阻斷任何對重要文件(夾)的訪問。這樣做能防止創建 allow 規則時可能的疏忽,使得配置文件不會太寬鬆。
  2. deny 規則執行時不會在日誌中記錄,使得後續執行 aa-logprof 時產生更為簡潔的日誌。需要注意的是,即使是在 complain 模式下,deny 規則也會被嚴格執行――因此,如果程序在 complain 模式下還是會出錯,應該檢查在某一配置文件或其包含的 abstraction 中,是否有一條 deny 規則導致了此問題。

另外,也可以手動編寫配置文件, 在此查看教程:AppArmor wiki - Profiling by hand

除了 /etc/apparmor.d/ 中的默認配置文件外,在 /usr/share/apparmor/extra-profiles/ 中還有更多預定義的配置文件。不過,這些配置文件並非一定適用於生產環境,因此可能需要手動修改或使用 aa-logprof(8)

也可以在 apparmor.d 項目處找到額外的 AppArmor 規則集。不過,直到撰寫本文時,該項目並非穩定可用。

解讀配置文件

配置文件是可讀性很高的文本文件,保存在 /etc/apparmor.d/ 下,定義了某個可執行文件的權限。以下是一個典型的配置文件:

/etc/apparmor.d/usr.bin.test
#include <tunables/global>

profile test /usr/lib/test/test_binary {
    #include <abstractions/base>

    # Main libraries and plugins
    /usr/share/TEST/** r,
    /usr/lib/TEST/** rm,

    # Configuration files and logs
    @{HOME}/.config/ r,
    @{HOME}/.config/TEST/** rw,
}

@ 符號開頭的字符串是在 abstraction(/etc/apparmor.d/abstractions/),tunables(/etc/apparmor.d/tunables/或配置文件本身中定義的變量。#include 將其他配置文件中的內容包含到此配置文件中來。路徑後的字符是訪問權限。使用 AppArmor 的通配符語法以實現模式匹配。

以下權限涵蓋了最常見的使用場景:

  • r — 讀取:讀取數據
  • w — 寫入:創建,刪除,寫入文件,或是附加內容到文件尾部
  • m — 映射:將文件映射為可執行內存
  • x — 執行:執行文件。需要在前面加上修飾符,形如 px(執行時切換配置文件)

注意,定義的權限始終無法使程序獲得大於原本在 DAC 中擁有的權限。

此處僅提到了很淺顯的內容。要查詢更為詳細的文檔,請查看 apparmor.d(5) 手冊頁和 官方文檔

提示與技巧

拒絕訪問後發出桌面通知

當 AppArmor 拒絕了程序的訪問後,通知進程可以顯示桌面通知。通過以下步驟,可以在登錄時自動啟動 aa-notify 進程:

安裝 Audit framework 並且啟動/啟用用戶空間的Linux Audit進程。之後將你的桌面用戶添加到 audit 用戶組,從而允許其讀取審計日誌(audit logs):

# groupadd -r audit
# gpasswd -a user audit

audit 用戶組添加到 auditd.conf

/etc/audit/auditd.conf
log_group = audit
提示:也可以使用已有的系統用戶組,例如 wheeladm

安裝 python-notify2python-psutil

創建一個桌面配置項並填入以下內容:

~/.config/autostart/apparmor-notify.desktop
[Desktop Entry]
Type=Application
Name=AppArmor Notify
Comment=Receive on screen notifications of AppArmor denials
TryExec=aa-notify
Exec=aa-notify -p -s 1 -w 60 -f /var/log/audit/audit.log
StartupNotify=false
NoDisplay=true

重啟並檢查進程 aa-notify 是否運行:

$ pgrep -ax aa-notify
注意:在一些特定的系統配置下,可能會有海量的消息彈出。

要查詢更多信息,參見 aa-notify(8)

緩存配置文件以提高 AppArmor 啟動速度

啟動時,AppArmor 需要將配置文件轉換為二進制格式,這一步可能會顯著延長啟動時間。可以用以下命令檢查當前 AppArmor 的啟動耗時:

$ systemd-analyze blame | grep apparmor

要啟用 AppArmor 配置文件緩存功能,取消注釋以下內容:

/etc/apparmor/parser.conf
## Turn creating/updating of the cache on by default
write-cache

要改變默認的緩存存儲位置,添加以下內容:

/etc/apparmor/parser.conf
cache-loc=/path/to/location
注意:自版本 2.13.1 起,默認的緩存存儲位置已經由 /etc/apparmor.d/cache.d/ 變為 /var/cache/apparmor/

重啟並再次檢查 AppArmor 啟動耗時,觀察有無改善:

$ systemd-analyze blame | grep apparmor

排錯

無法啟動 Samba SMB/CIFS 服務

參見 Samba#AppArmor_權限問題

升級到 AppArmor v4 後無法登錄

在非常罕見的情況下,升級到 AppArmor v4 會導致無法登錄到任何帳戶

系統日誌中可能包含類似如下內容的錯誤:

unix_chkpwd[1612]: check pass; user unknown
unix_chkpwd[1612]: password check failed for user (john)
gdm-password][1574]: pam_unix(gdm-password:auth): authentication failure; logname= uid=0 euid=0 tty=/dev/tty1 ruser= rhost=  user=john
kernel: audit: type=1400 audit(1730844640.468:171): apparmor="DENIED" operation="capable" class="cap" profile="unix-chkpwd" pid=1612 comm="unix_chkpwd" capability=2  capname="dac_read_search"
kernel: audit: type=1400 audit(1730844640.468:172): apparmor="DENIED" operation="capable" class="cap" profile="unix-chkpwd" pid=1612 comm="unix_chkpwd" capability=1  capname="dac_override"

這可能是由於 root 帳戶無法讀取 /etc/shadow 和/或 /etc/gshadow 導致的(例如,這些文件的權限位(Permission bits)尚未設定)。因此,可以試試以下解決辦法:

  1. 重啟,然後停用 AppArmor(在啟動時編輯 Bootloader 參數,或者使用尚未啟用 AppArmor 的 fallback 啟動項)。
  2. root 身份登錄,然後設定正確的文件權限:chmod 600 /etc/shadow /etc/gshadow
  3. 再次重啟。

不同 Linux 發行版之間的區別

大多數現有的資料是為運行在 Ubuntu 上的 AppArmor 編寫的,而這些並不完全適用於 Arch Linux,因為 Ubuntu 為 AppArmor 應用了許多內核補丁。其他的發行版也可能使用自己的內核補丁,但 Arch Linux 使用的是儘可能接近主線的內核。

例如,儘管 apparmor.d(5) 中已經提到了 dbus 規則,卻仍需要 AppArmor 用戶空間工具,內核和 D-Bus 守護進程[5]的支持。Ubuntu 已經應用了對應的內核補丁[6],但該補丁並未包含在 Linux 主線內核和 Arch 官方內核中。(是否支持也因 D-Bus 實現方式而異。)

Ubuntu 所使用的 AppArmor 特定內核補丁也可以在此處找到(將下文中的 oracular 替換為指定的 Ubuntu 版本代號):

https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/oracular/log/?qt=grep&q=UBUNTU%3A+SAUCE%3A+apparmor

受用戶空間工具支持的 ABI 版本也可以在 /etc/apparmor.d/abi/ 處找到。當前運行的內核所支持的 ABI 可以使用以下命令查看:

$ aa-features-abi --extract

參見