Ubuntuではセキュリティ対策の一環としてAppArmorを採用しています。前回の
AppArmorのおさらい
まずは前回のおさらいをしましょう。
AppArmorは/etc/
」
- enforced
(適用) モード:プロファイルで許可されていない処理を行おうとした場合は、エラー扱いにしログに残す - complaining
(学習) モード:プロファイルで許可されていない処理を行う場合、ログに残すものの、エラー扱いにはしない - unconfined
(非制限) モード:何も制限しない
新規にプロファイルを作る場合、もしくは既存のプロファイルをカスタマイズする場合は、とりあえずcomplainingモードで動かしてどのような操作が許可されていないかを確認し、その内容に合わせてプロファイルを書くことになります。
AppArmorプロファイルの作成
それではプロファイルのフォーマットを確認しながら、適当なプロファイルを作ってみましょう。
プロファイルを作るためにはターゲットとなるプログラムが必要になります。既存のプログラムに対してプロファイルを作っても良いのですが、変更に失敗してシステムの他の部分が動かなくなると大変です。そこで実行パスが通っていない場所に、既存のプログラムを移動して、それに対するプロファイルを作ってみましょう。おすすめはbusyboxです。busyboxはさまざまなプログラムの集合体であるため、これ単体でいろいろな機能を試せます。
まずはbusyboxを/opt/
に移動します。ためしにbusyboxのshアプレットを起動しましょう。
$ sudo mkdir -p /opt/sample/bin $ sudo cp /usr/bin/busybox /opt/sample/bin/ $ /opt/sample/bin/busybox sh BusyBox v1.30.1 (Ubuntu 1:1.30.1-7ubuntu3) built-in shell (ash) Enter 'help' for a list of built-in commands. ~ $ exit
このようにbusyboxは複数の機能
AppArmorにおいてプロファイルを作成・
aa-genprof
コマンドで特定のプログラムの様々な機能を使ってみて、対話的にプロファイルを生成する- 先にcomplainingモードで雛形を作成し、実際にプログラムを動かして記録されたログから、
aa-logprof
コマンドでプロファイルを変更する - 先にcomplainingモードで雛形を作成し、実際にプログラムを動かして記録されたログから、目視確認してプロファイルを変更する
新規に作成するなら一番上が最もかんたんです[1]。2番目・
aa-genprof
やaa-logprof
を使うのであれば、apparmor-utilsパッケージが必要です。あらかじめ次の手順でインストールしておいてください。
$ sudo apt install apparmor-utils
では試しに、aa-genprof
で作成するプログラムを指定します。最後の引数がAppArmorでいうところの、ターゲットとなるパスであり、プロファイルはこのパスをベースに
$ sudo aa-genprof /opt/sample/bin/busybox (中略) Please start the application to be profiled in another window and exercise its functionality now. Once completed, select the "Scan" option 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. [(S)can system log for AppArmor events] / (F)inish
これでプロファイル作成モードに入りました。あとは実際にプログラムを動かしながら権限が必要となりそうな操作を行います。このために
$ /opt/sample/bin/busybox sh BusyBox v1.30.1 (Ubuntu 1:1.30.1-7ubuntu3) built-in shell (ash) Enter 'help' for a list of built-in commands. ~ $ ls / bin cdrom etc lib lib64 lost+found mnt proc run snap swapfile tmp var boot dev home lib32 libx32 media opt root sbin srv sys usr ~ $ exit
ここでは試しにbusyboxのシェルを起動して、/
」aa-genprof
の端末に戻ってS
」
Reading log entries from /var/log/syslog. (中略) Complain-mode changes: 標準出力に出力しているため、コンソールの書き込み権限を許可するか、 もしくはそれらを定義しているabstractionファイルをロードするか確認: Profile: /opt/sample/bin/busybox Path: /dev/tty New Mode: rw Severity: 9 [1 - include <abstractions/consoles>] 2 - /dev/tty rw, (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / Abo(r)t / (F)inish Adding include <abstractions/consoles> to profile. (中略) [1 - include <abstractions/opencl-pocl>] 2 - / r, (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / Abo(r)t / (F)inish Adding include <abstractions/opencl-pocl> to profile. = Changed Local Profiles = The following local profiles were changed. Would you like to save them? [1 - /opt/sample/bin/busybox] (S)ave Changes / Save Selec(t)ed Profile / [(V)iew Changes] / View Changes b/w (C)lean profiles / Abo(r)t <= ここで「S」を押して保存 Writing updated profile for /opt/sample/bin/busybox. (中略) [(S)can system log for AppArmor events] / (F)inish <= ここで「F」を押して終了 Setting /opt/sample/bin/busybox to enforce mode. <= プロファイルがロードされる (中略) Finished generating profile for /opt/sample/bin/busybox.
「abstraction」/etc/
」
これでプロファイルの雛形が/etc/
」
$ sudo cat /etc/apparmor.d/opt.sample.bin.busybox
# Last Modified: Sat Jan 27 00:29:37 2024
abi <abi/3.0>,
include <tunables/global>
/opt/sample/bin/busybox {
include <abstractions/base>
include <abstractions/consoles>
include <abstractions/opencl-pocl>
/etc/passwd r,
/opt/sample/bin/busybox mr,
}
まずabi
」<abi/
」
AppArmorのプロファイルではファイルパス { 設定 }
」/opt/
」{ 設定 }
」#
」
include
文は、/etc/
」
tunables/
は基本的にすべてのプロファイルでロードしたほうが良いものをまとめてincludeしてくれるファイルですglobal abstractions/
は一般的なLinuxコマンドならまず必要になるであろう設定が入っていますbase abstractions/
は標準入出力を使うコマンドに必要な設定が入っていますconsoles abstractions/
はOpenCLを使う際に必要な設定が入っていますopencl-pocl
abstractions/
が選択されているのはbusyboxが標準入出力を使っていたからです。これについては/dev/
」
注意が必要なのはabstractions/
」ls /
」/
の読み込み権限」abstractions/
でも設定されている」aa-logprof
では次のようにどちらを使うかの問い合わせがありました。
[1 - include <abstractions/opencl-pocl>] 2 - / r, (A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / Abo(r)t / (F)inish Adding include <abstractions/opencl-pocl> to profile.
今回はOpenCLプログラムではないため、本来は2 - / r,
」/ r
」/
」/opt
」/** r
」/* r
」
最後の/etc/
」/opt/
」
r
:読み込みを許可するw
:書き込みを許可する?x
:実行を許可する( ?
の部分でさらに細かい調整をする)m
:mmap()
を許可するl
:リンクを許可するk
:ファイルロックを許可する
「/etc/
」/etc/
を読んでいたために追加されました。/opt/
」
さてaa-genprof
で作ったプロファイルは自動的にロードされています。ここで許可されていないコマンドを実行してみましょう。
$ /opt/sample/bin/busybox sh -c "ls /opt" ls: can't open '/opt': Permission denied
先ほど作ったプロファイルでは/
」/opt
」/** r
」sudo apparmor_
」
AppAromorプロファイルをさらにカスタマイズする
さらに別のアプレットを試してみましょう。たとえば管理者権限でpingコマンドを実行してもPermission denied
」
$ sudo /opt/sample/bin/busybox ping 127.0.0.1 PING 127.0.0.1 (127.0.0.1): 56 data bytes ping: can't create raw socket: Permission denied
せっかくなのでbusyboxのpingコマンドも実行できるように、プロファイルをカスタマイズしてみましょう。プロファイルの更新にもaa-genprof
を利用できます。先ほどと同じようにaa-genprof
を起動してください。
$ sudo aa-genprof /opt/sample/bin/busybox
別端末でpingコマンドを実行すると、先ほどと同じようなエラーになるはずです。
$ sudo /opt/sample/bin/busybox ping 127.0.0.1 PING 127.0.0.1 (127.0.0.1): 56 data bytes ping: can't create raw socket: Permission denied
aa-genprof
の端末に戻って、auditログをスキャンしてみましょう。
[(S)can system log for AppArmor events] / (F)inish Reading log entries from /var/log/syslog. Enforce-mode changes: Profile: /opt/sample/bin/busybox Network Family: inet Socket Type: raw [1 - network inet raw,] (A)llow / [(D)eny] / (I)gnore / Audi(t) / Abo(r)t / (F)inish
inetファミリーのrawソケットの利用権限が必要そうなので許可
Adding network inet raw, to profile. (中略) [1 - /opt/sample/bin/busybox] (S)ave Changes / Save Selec(t)ed Profile / [(V)iew Changes] / View Changes b/w (C)lean profiles / Abo(r)t Writing updated profile for /opt/sample/bin/busybox.
許可したら設定を保存します。このタイミングでプロファイルがリロードされます。本来ならここで終了なのですが、今回はaa-genprof
の端末はそのままにして、もう一度pingコマンドを実行してみましょう。
$ sudo /opt/sample/bin/busybox ping 127.0.0.1 PING 127.0.0.1 (127.0.0.1): 56 data bytes ping: permission denied (are you root?)
あれ、まだ成功しないようですね。aa-genprof
側でauditログを再スキャンしてみます。
Profile: /opt/sample/bin/busybox Capability: net_raw Severity: 8 [1 - capability net_raw,] (A)llow / [(D)eny] / (I)gnore / Audi(t) / Abo(r)t / (F)inish
どうやらnet_aa-genprof
を使う場合は、成功するまで何度も
$ sudo /opt/sample/bin/busybox ping 127.0.0.1 PING 127.0.0.1 (127.0.0.1): 56 data bytes 64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.064 ms 64 bytes from 127.0.0.1: seq=1 ttl=64 time=0.135 ms 64 bytes from 127.0.0.1: seq=2 ttl=64 time=0.135 ms ^C --- 127.0.0.1 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 0.064/0.111/0.135 ms
今度は無事に成功したようです。/etc/
」
capability net_raw, network inet raw,
このようにAppArmorのプロファイルの作成には、auditログを見ながら必要な権限をこまめに許可していく必要があります。aa-genprof
などである程度自動化できるとはいえ、適切な権限付与にはそれなりの手間と時間がかかりますし、プログラムに対する理解も必要です。
また、AppArmorのプロファイル自体、今回紹介したもの以外にもかなり多くの書式が存在し、柔軟な設定が可能です。プロファイルのフォーマットについてはapparmor.
まずはこれらの情報を元に、既存のプロファイルが何をやっているのか読み解くのも良いかもしれませんね。