Product SiteDocumentation Site

14.4. AppArmor の紹介

14.4.1. 原理

AppArmor は Linux の LSM (Linux Security Modules) インターフェース上に設けられた強制アクセス制御 (MAC) システムです。具体的に言えば、カーネルはそれぞれのシステムコールの前にシステムコールを発行したプロセスが指定された操作に対する権限を与えられているか AppArmor に問い合わせます。このメカニズムを通じて、AppArmor はプログラムがアクセスできるリソースを制限します。
AppArmor はプログラムごとに一連の規則 (これは「プロファイル」として知られています) を適用します。カーネルは実行されたプログラムのインストール先のパスに依存してこのプロファイルを適用します。SELinux とは対照的に (第 14.5 節「SELinux の紹介」を参照してください)、このプロファイルはユーザに依存するものではありません。同じプログラムを実行したすべてのユーザは同じプロファイルを適用されます (しかしながら、伝統的なユーザパーミッションが適用されないわけではありません。このため、ユーザごとにプログラムの挙動が異なる可能性もあります!)。
AppArmor プロファイルは /etc/apparmor.d/ に保存され、プロファイルには各プログラムが使うことができるリソースに対するアクセス制御規則のリストが含まれています。プロファイルは apparmor_parser コマンドによってコンパイルされてカーネルに読み込まれます。各プロファイルは enforce または complain モードで読み込みます。enforce モードではポリシーの遵守を強制され、ポリシー違反の試行を報告されます。これに対して、complain モードではポリシーの遵守を強制されませんが、ポリシー違反で拒否されうるシステムコールを記録されます。

14.4.2. AppArmor の有効化と AppArmor プロファイルの管理

AppArmor support is built into the standard kernels provided by Debian. Enabling AppArmor is thus just a matter of installing some packages by executing apt install apparmor apparmor-profiles apparmor-utils with root privileges.
AppArmor is functional after the installation, and aa-status will confirm it quickly:
# aa-status
apparmor module is loaded.
40 profiles are loaded.
23 profiles are in enforce mode.
   /usr/bin/evince
   /usr/bin/evince-previewer
[...]
17 profiles are in complain mode.
   /usr/sbin/dnsmasq
[...]
14 processes have profiles defined.
12 processes are in enforce mode.
   /usr/bin/evince (3462)
[...]
2 processes are in complain mode.
   /usr/sbin/avahi-daemon (429) avahi-daemon
   /usr/sbin/avahi-daemon (511) avahi-daemon
0 processes are unconfined but have a profile defined.
それぞれのプロファイルの状態を enforce または complain モードに切り替えるには、引数に実行ファイルのパスかポリシーファイルのパスを与えて aa-enforce または aa-complain を呼び出します。さらにプロファイルを完全に無効化するには、aa-disable を使うか aa-audit を使ってプロファイルを audit モード (承認されたシステムコールもログ記録するモード) に切り替えます。
# aa-enforce /usr/bin/pidgin
Setting /usr/bin/pidgin to enforce mode.
# aa-complain /usr/sbin/dnsmasq
Setting /usr/sbin/dnsmasq to complain mode.

14.4.3. 新規プロファイルの作成

AppArmor プロファイルを作成することはかなり簡単な作業であるにも関わらず、多くのプログラムがプロファイルを用意していません。この節では、対象のプログラムを使いながら AppArmor に対象のプログラムが呼び出したシステムコールとアクセスするリソースを監視させることにより、ゼロから新しいプロファイルを作成する方法を示します。
アクセス制限を設ける必要のある最も重要なプログラムはネットワークを取り扱うプログラムです。なぜなら、この種のプログラムは遠隔攻撃者からの標的になるからです。このため好都合なことに AppArmor には aa-unconfined コマンドが用意されています。aa-unconfined コマンドは関連するプロファイルが存在せず開かれたネットワークソケットを公開しているプログラムを表示します。aa-unconfined--paranoid オプションを付けて実行すれば、少なくとも 1 つ以上のアクティブなネットワーク接続を持つアクセス制限を設けていないプロセスがすべて表示されます。
# aa-unconfined
801 /sbin/dhclient not confined
409 /usr/sbin/NetworkManager not confined
411 /usr/sbin/cupsd confined by '/usr/sbin/cupsd (enforce)'
429 /usr/sbin/avahi-daemon confined by 'avahi-daemon (enforce)'
516 /usr/sbin/cups-browsed confined by '/usr/sbin/cups-browsed (enforce)'
538 /usr/sbin/zebra not confined
591 /usr/sbin/named not confined
847 /usr/sbin/mysqld not confined
849 /usr/sbin/sshd not confined
1013 /usr/sbin/dhclient (/sbin/dhclient) not confined
1276 /usr/sbin/apache2 not confined
1322 /usr/sbin/apache2 not confined
1323 /usr/sbin/apache2 not confined
1324 /usr/sbin/apache2 not confined
1325 /usr/sbin/apache2 not confined
1327 /usr/sbin/apache2 not confined
1829 /usr/lib/ipsec/charon confined by '/usr/lib/ipsec/charon (enforce)'
2132 /usr/sbin/exim4 not confined
12865 /usr/bin/python3.7 (/usr/bin/python3) not confined
12873 /usr/bin/python3.7 (/usr/bin/python3) not confined
In the following example, we will thus try to create a profile for /sbin/dhclient. For this we will use aa-genprof dhclient. On Debian Buster, there is a known bug (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=928160) that makes the previous command may fail with the following error: ERROR: Include file /etc/apparmor.d/local/usr.lib.dovecot.deliver not found. To fix it create the missing files with touch file. It will invite you to use the application in another window and when done to come back to aa-genprof to scan for AppArmor events in the system logs and convert those logs into access rules. For each logged event, it will make one or more rule suggestions that you can either approve or further edit in multiple ways:
# aa-genprof dhclient
Writing updated profile for /usr/sbin/dhclient.
Setting /usr/sbin/dhclient 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:
https://gitlab.com/apparmor/apparmor/wikis/Profiles

Profiling: /usr/sbin/dhclient

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
Reading log entries from /var/log/syslog.
Updating AppArmor profiles in /etc/apparmor.d.

Profile:  /usr/sbin/dhclient 1
Execute:  /usr/sbin/dhclient-script
Severity: unknown

(I)nherit / (C)hild / (P)rofile / (N)amed / (U)nconfined / (X) ix On / (D)eny / Abo(r)t / (F)inish
P
Should AppArmor sanitise the environment when
switching profiles?

Sanitising environment is more secure,
but some applications depend on the presence
of LD_PRELOAD or LD_LIBRARY_PATH.

(Y)es / [(N)o]
Y
Writing updated profile for /usr/sbin/dhclient-script.
Complain-mode changes:

Profile:    /usr/sbin/dhclient 2
Capability: net_raw
Severity:   8

 [1 - capability net_raw,]
[(A)llow] / (D)eny / (I)gnore / Audi(t) / Abo(r)t / (F)inish
A
Adding capability net_raw to profile.

Profile:  /sbin/dhclient
Capability: net_bind_service
Severity:   8

 [1 - #include <abstractions/nis> ]
  2 - capability net_bind_service,
(A)llow / [(D)eny] / (I)gnore / Audi(t) / Abo(r)t / (F)inish
A
Adding #include <abstractions/nis> to profile.

Profile:  /usr/sbin/dhclient 3
Path:     /etc/ssl/openssl.cnf
New Mode: owner r
Severity: 2

 [1 - #include <abstractions/lightdm>]
  2 - #include <abstractions/openssl>
  3 - #include <abstractions/ssl_keys>
  4 - owner /etc/ssl/openssl.cnf r,
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish
2

Profile:  /usr/sbin/dhclient
Path:     /etc/ssl/openssl.cnf
New Mode: owner r
Severity: 2

  1 - #include <abstractions/lightdm>
 [2 - #include <abstractions/openssl>]
  3 - #include <abstractions/ssl_keys>
  4 - owner /etc/ssl/openssl.cnf r,
[(A)llow] / (D)eny / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Abo(r)t / (F)inish / (M)ore
A
[...]
Profile:  /usr/sbin/dhclient-script 4
Path:     /usr/bin/dash
New Mode: owner r
Severity: unknown

 [1 - #include <abstractions/lightdm>]
  2 - #include <abstractions/ubuntu-browsers.d/plugins-common>
  3 - owner /usr/bin/dash r,
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Audi(t) / (O)wner permissions off / Abo(r)t / (F)inish
A
Adding #include <abstractions/lightdm> to profile.
Deleted 2 previous matching profile entries.

= Changed Local Profiles =

The following local profiles were changed. Would you like to save them?

 [1 - /usr/sbin/dhclient]
  2 - /usr/sbin/dhclient-script
(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 /usr/sbin/dhclient.
Writing updated profile for /usr/sbin/dhclient-script.

Profiling: /usr/sbin/dhclient

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
F
Reloaded AppArmor profiles in enforce mode.

Please consider contributing your new profile!
See the following wiki page for more information:
https://gitlab.com/apparmor/apparmor/wikis/Profiles

Finished generating profile for /usr/sbin/dhclient.
aa-genprof プログラムはユーザが入力した操作文字を再表示しないという点に注意してください。しかし、上に挙げた例では説明を明確に行うために、ユーザが入力した操作文字をその直後に表記しています。

1

最初に別のプログラムである nm-dhcp-helper の実行イベントが検出されています。この場合、ユーザに対していくつかの選択肢が示されます。ユーザは dhclient のプロファイルを適用して nm-dhcp-helper を実行したり (「Inherit」を選んだ場合)、専用のプロファイルを適用して nm-dhcp-helper を実行したり (「Profile」と「Named」を選んだ場合。両者の違いは任意のプロファイル名を使用する可能性があるか否かです)、dhclient のサブプロファイルを適用して nm-dhcp-helper を実行したり (「Child」を選んだ場合)、プロファイルを適用せずに nm-dhcp-helper を実行したり (「Unconfined」を選んだ場合)、nm-dhcp-helper の実行を拒否したり (「Deny」を選んだ場合) することも可能です。
ここでまだ存在しない専用プロファイルを適用して nm-dhcp-helper を実行することを選んだ場合、aa-genprof ツールは不足しているプロファイルを作成し、さらにこのプロファイルに対する規則を提案します。この点に注意してください。

2

カーネルレベルでは root ユーザの特権が「capability」に分割されます。dhclient からのシステムコールが特定の「capability」を要求する場合、AppArmor はプロファイルの中でプログラムがその「capability」を使うことを許可されているかを確認します。

3

Here the program seeks read permissions for /etc/ssl/openssl.cnf. aa-genprof detected that this permission was also granted by multiple “abstractions” and offers them as alternative choices. An abstraction provides a reusable set of access rules grouping together multiple resources that are commonly used together. In this specific case, the file is generally accessed through the nameservice related functions of the C library and we type “2” to first select the “#include <abstractions/openssl>” choice and then “A” to allow it.

4

Notice that this access request is not part of the dhclient profile but of the new profile that we created when we allowed /usr/sbin/dhclient-script to run with its own profile.
ログ記録されたすべてのイベントを検討した後、aa-genprof プログラムは実行中に作成されたすべてのプロファイルを保存することを提案します。今回の場合、2 つのプロファイルを「Save」を使って一度に保存した後 (1 つずつ保存することも可能です)、「Finish」でプログラムを終了しています。
実際のところ aa-genprofaa-logprof の洗練されたラッパーに過ぎません。すなわち aa-genprof は空のプロファイルを作成し、complain モードでそのプロファイルを読み込み、aa-logprof を実行しているだけです。aa-logprof はログ記録されたプロファイル違反に基づいてプロファイルを更新するツールです。このため、たった今作成したプロファイルを改良するために aa-genprof をもう一度実行することが可能です。
If you want the generated profile to be complete, you should use the program in all the ways that it is legitimately used. In the case of dhclient, it means running it via Network Manager, running it via ifupdown, running it manually, etc. In the end, you might get a /etc/apparmor.d/usr.sbin.dhclient close to this:
# Last Modified: Fri Jul  5 00:51:02 2019
#include <tunables/global>

/usr/sbin/dhclient {
  #include <abstractions/base>
  #include <abstractions/nameservice>

  capability net_bind_service,
  capability net_raw,

  /bin/dash r,
  /etc/dhcp/* r,
  /etc/dhcp/dhclient-enter-hooks.d/* r,
  /etc/dhcp/dhclient-exit-hooks.d/* r,
  /etc/resolv.conf.* w,
  /etc/samba/dhcp.conf.* w,
  /proc/*/net/dev r,
  /proc/filesystems r,
  /run/dhclient*.pid w,
  /sbin/dhclient mr,
  /sbin/dhclient-script rCx,
  /usr/lib/NetworkManager/nm-dhcp-helper Px,
  /var/lib/NetworkManager/* r,
  /var/lib/NetworkManager/*.lease rw,
  /var/lib/dhcp/*.leases rw,

  owner /etc/** mrwk,
  owner /var/** mrwk,
  owner /{,var/}run/** mrwk,
}
And /etc/apparmor.d/usr.sbin.dhclient-script might be similar to this:
# Last Modified: Fri Jul  5 00:51:55 2019
#include <tunables/global>

/usr/sbin/dhclient-script {
  #include <abstractions/base>
  #include <abstractions/bash>
  #include <abstractions/lightdm>
}