AppArmor 概述
AppArmor(Application Armor)是 Linux 核心的安全模組,提供強制存取控制(Mandatory Access Control,MAC)機制。它透過設定檔(profile)來限制程式的能力,包括網路存取、檔案讀寫權限、執行其他程式等功能。Ubuntu 從 7.10 版本開始就將 AppArmor 作為預設的安全框架。
什麼是強制存取控制(MAC)?
傳統的 Linux 權限系統採用自主存取控制(Discretionary Access Control,DAC),由檔案擁有者決定誰可以存取檔案。然而,DAC 有個致命缺點:一旦程式被入侵,攻擊者就能以該程式的身份執行任何操作。
MAC 則不同,它由系統管理員定義安全政策,即使程式被入侵,攻擊者的行為仍會受到預先定義的政策限制。這種「最小權限原則」可以有效降低系統被攻擊後的損害範圍。
AppArmor 與 SELinux 比較
Linux 上主要有兩個 MAC 實作:AppArmor 和 SELinux。以下是兩者的比較:
| 特性 | AppArmor | SELinux |
|---|
| 預設採用 | Ubuntu、SUSE | RHEL、CentOS、Fedora |
| 基於 | 路徑(Path-based) | 標籤(Label-based) |
| 學習曲線 | 較平緩 | 較陡峭 |
| 設定複雜度 | 較簡單 | 較複雜 |
| 細緻度 | 中等 | 非常細緻 |
| 效能影響 | 較小 | 較小 |
AppArmor 的優勢
- 易於理解:使用檔案路徑定義規則,直覺易懂
- 部署簡單:不需要修改檔案系統或重新標記檔案
- 學習模式:提供 complain 模式,方便建立和測試設定檔
- Ubuntu 原生支援:與 Ubuntu 生態系統深度整合
檢查 AppArmor 狀態
確認 AppArmor 是否啟用
1
2
3
4
5
6
7
8
| # 檢查 AppArmor 核心模組是否載入
sudo aa-enabled
# 查看詳細狀態
sudo aa-status
# 或使用 apparmor_status(aa-status 的別名)
sudo apparmor_status
|
aa-status 輸出解讀
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| $ sudo aa-status
apparmor module is loaded.
47 profiles are loaded.
45 profiles are in enforce mode.
/snap/snapd/19457/usr/lib/snapd/snap-confine
/usr/bin/evince
/usr/bin/man
...
2 profiles are in complain mode.
/usr/sbin/cups-browsed
/usr/sbin/cupsd
4 processes have profiles defined.
4 processes are in enforce mode.
/usr/sbin/cups-browsed (1234)
0 processes are in complain mode.
0 processes are unconfined but have a profile defined.
|
檢查核心是否支援 AppArmor
1
2
3
4
5
6
| # 檢查核心設定
cat /sys/module/apparmor/parameters/enabled
# 輸出 Y 表示已啟用
# 查看 AppArmor 安全檔案系統
ls /sys/kernel/security/apparmor/
|
設定檔模式
AppArmor 的設定檔有三種主要模式:
1. Enforce 模式(強制模式)
在此模式下,AppArmor 會強制執行設定檔中的規則。任何違反規則的操作都會被拒絕並記錄到日誌。
1
2
3
4
5
| # 將設定檔切換到 enforce 模式
sudo aa-enforce /etc/apparmor.d/usr.bin.firefox
# 或指定程式路徑
sudo aa-enforce /usr/bin/firefox
|
2. Complain 模式(抱怨模式)
在此模式下,AppArmor 只會記錄違規操作,但不會阻止。這對於測試和建立新設定檔非常有用。
1
2
3
4
5
| # 將設定檔切換到 complain 模式
sudo aa-complain /etc/apparmor.d/usr.bin.firefox
# 或指定程式路徑
sudo aa-complain /usr/bin/firefox
|
3. Disable 模式(停用模式)
完全停用特定程式的 AppArmor 設定檔。
1
2
3
4
| # 停用設定檔
sudo aa-disable /etc/apparmor.d/usr.bin.firefox
# 這會建立一個符號連結到 /etc/apparmor.d/disable/ 目錄
|
常用管理指令
安裝 AppArmor 工具套件
1
2
3
4
5
6
| # 安裝 AppArmor 管理工具
sudo apt update
sudo apt install apparmor-utils
# 安裝額外的設定檔
sudo apt install apparmor-profiles apparmor-profiles-extra
|
aa-status - 查看狀態
1
2
3
4
5
| # 查看所有設定檔狀態
sudo aa-status
# 以 JSON 格式輸出
sudo aa-status --json
|
aa-enforce - 強制模式
1
2
3
4
5
| # 將特定設定檔設為強制模式
sudo aa-enforce /etc/apparmor.d/usr.sbin.tcpdump
# 將所有設定檔設為強制模式
sudo aa-enforce /etc/apparmor.d/*
|
aa-complain - 抱怨模式
1
2
3
4
5
| # 將特定設定檔設為抱怨模式
sudo aa-complain /etc/apparmor.d/usr.sbin.tcpdump
# 將所有設定檔設為抱怨模式
sudo aa-complain /etc/apparmor.d/*
|
重新載入設定檔
1
2
3
4
5
6
7
8
| # 重新載入特定設定檔
sudo apparmor_parser -r /etc/apparmor.d/usr.bin.firefox
# 重新載入所有設定檔
sudo systemctl reload apparmor
# 或使用 service 指令
sudo service apparmor reload
|
解除載入設定檔
1
2
| # 解除載入特定設定檔
sudo apparmor_parser -R /etc/apparmor.d/usr.bin.firefox
|
設定檔結構與語法
AppArmor 設定檔位於 /etc/apparmor.d/ 目錄下,命名慣例是將程式路徑中的斜線替換為點號。
設定檔基本結構
1
2
| # 查看設定檔目錄
ls -la /etc/apparmor.d/
|
一個典型的設定檔結構如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| #include <tunables/global>
/usr/bin/example {
#include <abstractions/base>
# 檔案存取規則
/etc/example.conf r,
/var/log/example.log w,
/tmp/example/** rw,
# 程式執行規則
/usr/bin/helper ix,
# 網路規則
network inet stream,
# 能力(capabilities)
capability net_bind_service,
}
|
檔案權限旗標
| 旗標 | 說明 |
|---|
| r | 讀取 |
| w | 寫入 |
| a | 附加(append) |
| x | 執行 |
| m | 記憶體映射執行 |
| k | 檔案鎖定 |
| l | 建立硬連結 |
| ix | 繼承執行(inherit execute) |
| px | 轉換到指定設定檔執行 |
| Px | 轉換到指定設定檔執行(清除環境) |
| ux | 不受限制執行(unconfined) |
| Ux | 不受限制執行(清除環境) |
使用抽象檔案
AppArmor 提供許多預定義的抽象檔案,包含常見的存取規則:
1
2
3
4
5
6
7
8
| # 查看可用的抽象檔案
ls /etc/apparmor.d/abstractions/
# 常用的抽象檔案
# base - 基本系統存取
# nameservice - DNS 和使用者資訊查詢
# authentication - 認證相關
# ssl_certs - SSL 憑證存取
|
建立自訂設定檔
手動建立設定檔
以下是為一個簡單的 Python 腳本建立設定檔的範例:
1
2
| # 建立設定檔
sudo nano /etc/apparmor.d/usr.local.bin.myscript
|
設定檔內容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| #include <tunables/global>
/usr/local/bin/myscript.py {
#include <abstractions/base>
#include <abstractions/python>
# 程式本身
/usr/local/bin/myscript.py r,
# Python 解譯器
/usr/bin/python3* ix,
# 允許讀取設定檔
/etc/myscript/*.conf r,
# 允許寫入日誌
/var/log/myscript.log w,
# 允許讀寫資料目錄
/var/lib/myscript/** rw,
# 網路存取
network inet tcp,
}
|
載入設定檔:
1
2
3
4
5
| # 載入新設定檔
sudo apparmor_parser -r /etc/apparmor.d/usr.local.bin.myscript
# 確認載入成功
sudo aa-status | grep myscript
|
使用 aa-genprof 產生設定檔
aa-genprof 是一個互動式工具,可以自動產生 AppArmor 設定檔。
基本使用流程
1
2
3
4
5
6
7
8
9
| # 1. 開始產生設定檔(此指令會進入互動模式)
sudo aa-genprof /usr/bin/example
# 2. 在另一個終端機中,執行目標程式並測試各種功能
/usr/bin/example
# 3. 回到 aa-genprof 視窗,按 S 掃描日誌
# 4. 根據提示選擇允許或拒絕各項存取
# 5. 按 F 完成並儲存設定檔
|
aa-genprof 互動選項
| 選項 | 說明 |
|---|
| A | 允許(Allow) |
| D | 拒絕(Deny) |
| I | 繼承(Inherit) |
| G | 使用 Glob 萬用字元 |
| N | 新增設定檔規則 |
| S | 掃描系統日誌 |
| F | 完成並儲存 |
使用 aa-logprof 更新設定檔
當程式行為改變時,可以使用 aa-logprof 更新現有設定檔:
1
2
3
4
5
| # 掃描日誌並更新所有設定檔
sudo aa-logprof
# 指定日誌檔案
sudo aa-logprof -f /var/log/syslog
|
除錯與日誌分析
查看 AppArmor 日誌
AppArmor 的日誌訊息會記錄在系統日誌中:
1
2
3
4
5
6
7
8
9
10
11
| # 使用 dmesg 查看核心訊息
sudo dmesg | grep apparmor
# 使用 journalctl 查看
sudo journalctl -k | grep apparmor
# 查看 audit 日誌(如果已安裝 auditd)
sudo ausearch -m AVC -ts recent
# 查看 syslog
sudo grep "apparmor" /var/log/syslog
|
日誌訊息解讀
典型的 AppArmor 拒絕訊息:
1
| audit: type=1400 audit(1234567890.123:456): apparmor="DENIED" operation="open" profile="/usr/bin/example" name="/etc/passwd" pid=1234 comm="example" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
|
重要欄位說明:
| 欄位 | 說明 |
|---|
| apparmor | DENIED(拒絕)或 ALLOWED(允許) |
| operation | 被攔截的操作類型 |
| profile | 使用的設定檔 |
| name | 被存取的資源 |
| requested_mask | 請求的權限 |
| denied_mask | 被拒絕的權限 |
使用 aa-notify 監控
1
2
3
4
5
6
7
8
| # 安裝 aa-notify
sudo apt install apparmor-notify
# 即時監控 AppArmor 事件
sudo aa-notify -p -f /var/log/syslog
# 設定桌面通知
aa-notify -p --display $DISPLAY
|
常見問題排除
問題:程式無法正常運作
1
2
3
4
5
6
7
8
9
10
| # 1. 將設定檔改為 complain 模式
sudo aa-complain /etc/apparmor.d/profile_name
# 2. 執行程式並檢查日誌
sudo aa-logprof
# 3. 根據日誌調整設定檔
# 4. 改回 enforce 模式測試
sudo aa-enforce /etc/apparmor.d/profile_name
|
問題:找不到設定檔
1
2
3
| # 確認設定檔命名正確
# 設定檔名稱應該是程式路徑,將 / 替換為 .
# 例如:/usr/bin/firefox -> usr.bin.firefox
|
參考資料