Ubuntu 22.04 AppArmor 安全模組設定

Ubuntu 22.04 AppArmor Security Module Configuration

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。以下是兩者的比較:

特性AppArmorSELinux
預設採用Ubuntu、SUSERHEL、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

重要欄位說明:

欄位說明
apparmorDENIED(拒絕)或 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

參考資料

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy