03 December 2012

(Linux) AppArmorによるファイルアクセス制御

AppArmorの使い方を習得するため、簡単なファイルアクセス制御を試してみた。

■ 検証環境
・Ubuntu 12.04LTS (参考資料 Ubuntu documentation : AppArmor

■ まず、プロファイルのスケルトンを作成する

# aa-genprof /home/user/workspace/test Writing updated profile for /home/user/workspace/test. Setting /home/user/workspace/test to complain mode. Before you begin, you may wish to check if a profile already exists for the application you wish to confine. See the following wiki page for more information: http://wiki.apparmor.net/index.php/Profiles Please start the application to be profiled in another window and exercise its functionality now. Once completed, select the "Scan" button below in order to scan the system logs for AppArmor events. For each AppArmor event, you will be given the opportunity to choose whether the access should be allowed or denied. Profiling: /home/user/workspace/test [(S)can system log for AppArmor events] / (F)inish ← F キーを押す Setting /home/user/workspace/test to enforce mode. Reloaded AppArmor profiles in enforce mode. Please consider contributing your new profile! See the following wiki page for more information: http://wiki.apparmor.net/index.php/Profiles Finished generating profile for /home/user/workspace/test.

/etc/apparmor.d/ ディレクトリにプロファイルの骨格が作成される

/etc/apparmor.d/home.user.workspace.test
# Last Modified: Mon Dec 3 22:23:45 2012 #include <tunables/global> /home/user/workspace/test { #include <abstractions/base> /home/user/workspace/test mr, }

■ テスト用プログラムを作成し、コンパイル

/home/user/workspace/test.c
#include <stdio.h> #include <stdlib.h> void main(void){ FILE *fp; printf("File write test ...\n"); fp = fopen("test.dat", "w"); if(fp == NULL){ printf("file open error\n"); exit(0); } fprintf(fp, "test\n"); fclose(fp); printf("write success\n"); }

このプログラムをコンパイルし、test という実行ファイルを作成

$ gcc test.c -o test

■ AppArmorでテストプログラム用プロファイルを有効化する

# aa-enforce /home/user/workspace/test Setting /home/user/workspace/test to enforce mode. # invoke-rc.d apparmor reload * Reloading AppArmor profiles Skipping profile in /etc/apparmor.d/disable: usr.bin.firefox Skipping profile in /etc/apparmor.d/disable: usr.sbin.rsyslogd [ OK ]

■ テスト用プログラムを実行し、AppArmorで追加すべきルールを見つけ出す

テスト用プログラムを実行し、syslogを観察すると…

# cat /var/log/syslog | grep test Dec 3 22:43:42 s5350-ubuntu-1204 kernel: [ 6672.074597] type=1400 audit(1354542222.088:696): apparmor="DENIED" operation="open" parent=3138 profile="/home/user/workspace/test" name="/home/user/workspace/test.dat" pid=6954 comm="test" requested_mask="wc" denied_mask="wc" fsuid=1001 ouid=1001

AppArmorで拒否されたファイルアクセスを発見した

■ AppArmorのプロファイルに、ファイル書きこみルールを追加する

/etc/apparmor.d/home.user.workspace.test
# Last Modified: Mon Dec 3 22:23:45 2012 #include <tunables/global> /home/user/workspace/test { #include <abstractions/base> /home/user/workspace/test mr, /home/user/workspace/test.dat rw, }

AppArmorのプロファイルを再読みこみさせれば、テスト用プログラムは問題なく動くようになる

ファイルアクセスの許可書式は

短い形式長い形式許可内容の説明
rreadファイルの読み込み許可
wwriteファイルの書き込み許可
aappendファイルの新規作成と追記許可(O_APPENDでfopenする場合)
createファイルの作成許可
deleteファイルの削除許可
renameファイルの名称変更許可
llinkファイルへのリンク作成許可
klockファイルのロック許可
xexecファイルの実行許可

※writeを指定すれば、create, delete, rename, chmod, chownなどの許可も同時に与えられる。

■ Perlスクリプトの場合

/home/user/workspace/test.pl
#!/usr/bin/perl use strict; use warnings; print "File write test\n"; open(FH, "> test.dat") or die("file open error\n"); print(FH "test\n") or die("file write error\n"); close(FH); print "write success\n";

このスクリプトファイル自体に実行許可を与えた場合に、AppArmorで制御が出来るようになる。perl test.plのように呼び出した場合は/usr/bin/perlが制御対象で、test.plはperlというプログラムから呼び出される一つのデータファイルに過ぎない。
/usr/bin/perl のプロファイルを作成して、適切に継承関係設定すれば何とかなるのかもしれないが…

$ chmod + test.pl $ ./test.pl

Apparmorのプロファイルは次のようになる

/etc/apparmor.d/home.user.workspace.test.pl
# Last Modified: Mon Dec 3 20:24:46 2012 #include <tunables/global> /home/user/workspace/test.pl { #include <abstractions/base> #include <abstractions/perl> /home/user/workspace/test.pl r, /home/user/workspace/test.dat w, }

■ 参考資料
AppArmor (2.3.1) Quick Start
AppArmor Core Policy Reference