傳統的自由選定存取控制 DAC(discretionary access control)情況下,一旦拿到 root 權限就等同於橫行無阻,所以強制存取控制 MAC (mandatory access control) 的概念就出現了。由作業系統約束的存取控制,目標是限制"主體"訪問"客體"或"主體"執行某種操作的能力。在實踐中,主體通常是一個程式或是行程,客體可能是檔案、目錄、TCP/UDP埠、共享記憶體段、I/O裝置等。
依照 wiki 的定義,AppArmor (「Application Armor」,意為「應用盔甲」) 是一個Linux核心安全模組,允許系統管理員通過每個程式的設定檔限制程式的功能。簡單來說 AppArmor 是一套可以限制程式存取系統資源的機制。
以下接就透過一個簡單範例來測試 AppArmor 的限制能力。先編寫一支會讀取檔案內容的 C 語言程式。
#include <stdio.h>
int main() {
FILE *fptr;
// Open a file in read mode
fptr = fopen("test.txt", "r");
// Store the content of the file
char myString[100];
// If the file exist
if(fptr != NULL) {
// Read the content and print it
while(fgets(myString, 100, fptr)) {
printf("%s", myString);
}
// If the file does not exist
} else {
printf("Not able to open the file.");
}
// Close the file
fclose(fptr);
}
# 確認一下 apparmor 的服務狀態
sudo systemctl status apparmor ;
gcc read_file.c ;
echo 1233 > test.txt ;
./a.out ;
# Ubuntu 22.04 專用
sudo apt install -y python3-apparmor=3.0.4-2ubuntu2 ;
# Ubuntu 22.04 專用
sudo apt install -y apparmor-utils=3.0.4-2ubuntu2 ;
# 透過 aa-easyprof 針對程式產出設定檔
aa-easyprof ~/a.out > usr.bin.a.out ;
# 把設定檔移動到 apparmor 的資料夾底下
sudo mv usr.bin.a.out /etc/apparmor.d ;
# 套用設定檔,因為內部包含程式絕對路徑,所以會自動對應到
sudo apparmor_parser -r /etc/apparmor.d/usr.bin.a.out ;
# 觀察目前套用的設定檔
sudo aa-status ;
# 執行程式,會發現失敗惹,因為目前設定檔並沒有開放任何東西
./a.out ;
tail -f /var/log/syslog | grep apparmor ;
# 將 a.out 切換成抱怨模式
sudo aa-complain a.out ;
# 觀察一下 a.out 目前的狀態
sudo aa-status ;
# 這時候執行程式會成功
./a.out ;
# 透過程式進行互動模式決定是否要允許
# 先輸入 (A)llow,再輸入 (S)ave Changes
sudo aa-logprof ;
# 觀察 profile 檔案的內容差異
cat /etc/apparmor.d/usr.bin.a.out ;
# 將 a.out 切換成強制模式
sudo aa-enforce a.out ;
# 這時候執行就會成功
./a.out ;
Apparmor 策略編寫可以參考 Profile Components and Syntax。這篇是我目前在網路上找到覺得寫得最詳盡的,當然明天也會繼續這部分的解說。
作業7 : Apparmor 的阻擋是針對檔案路徑去做進行阻擋的,也就是說動用你的頭腦就可發現繞過的方法,請在開啟強制模式下並且不修改及編譯程式的情況下試著繞過看看。
# 重新產生設定檔,並蓋過原本檔案後進行套用
aa-easyprof $(pwd)/a.out > usr.bin.a.out ;
sudo mv usr.bin.a.out /etc/apparmor.d ;
sudo apparmor_parser -r /etc/apparmor.d/usr.bin.a.out ;
# 將 a.out 切換成強制模式
sudo aa-enforce a.out ;
# 無法執行,請想辦法繞過限制
./a.out ;