Chapter 7: ポリシーの適用はどのように行いますか?
7.1. 強制モードを有効にする
ドメインポリシーと例外ポリシーの調整が完了したら、ドメインに対して強制モードを割り当てることができます。
ポリシーエディタを実行して、対象となるドメインにプロファイル 3 を割り当てます:
@ キーを押してプロセス一覧表示に切り替えてください。そして、 /usr/sbin/httpd
プロセスとその子孫に対してプロファイル 3 が割り当てられていることを確認してください:
ポリシーエディタを終了して、ポリシーで許可されている操作をしてみましょう:
メールの送信はポリシーで許可されているので、操作は正常に終了しました。
ポリシーで許可されていない操作をしてみましょう:
一見すると正常に終了したように見えますが、実際には /bin/mail
が「入力が空っぽです」と警告しているとおり、 /bin/cat
の実行が拒否されています:
確認モードと同様、 /sys/kernel/security/tomoyo/stat インタフェースからポリシー違反の発生回数と最後に発生した時刻について知ることができます:
# cat /sys/kernel/security/tomoyo/stat
Policy update: 1571 (Last: 2010/12/25 16:10:48) Policy violation in learning mode: 453 (Last: 2010/12/25 15:33:21) Policy violation in permissive mode: 22 (Last: 2010/12/25 15:47:10) Policy violation in enforcing mode: 2 (Last: 2010/12/25 16:08:35) Memory used by policy: 165728 Memory used by audit log: 0 (Quota: 16777216) Memory used by query message: 0 (Quota: 1048576) Total memory used: 165728
もしアクセスログの設定を 4.6. アクセスログを保存する(任意)で行っていた場合は、拒否されたアクセス要求を /var/log/tomoyo/reject_003.log から抽出することができます:
# cat /var/log/tomoyo/reject_003.log
#2010/12/25 16:08:35# profile=3 mode=enforcing granted=no (global-pid=3628) task={ pid=3628 ppid=3627 uid=48 gid=48 euid=48 egid=48 suid=48 sgid=48 fsuid=48 fsgid=48 } path1={ uid=0 gid=0 ino=688153 major=8 minor=1 perm=0755 type=file } path1.parent={ uid=0 gid=0 ino=688129 perm=0755 } exec={ realpath="/bin/cat" argc=2 envc=7 argv[]={ "cat" "/etc/passwd" } envp[]={ "TERM=vt100" "PATH=/sbin:/usr/sbin:/bin:/usr/bin" "_=/bin/cat" "PWD=/usr/share/horde/admin" "LANG=en_US.UTF-8" "SHLVL=3" "LANGUAGE=en_US.UTF-8" } } <kernel> /usr/sbin/httpd /bin/sh file execute /bin/cat #2010/12/25 16:08:35# profile=3 mode=enforcing granted=no (global-pid=3628) task={ pid=3628 ppid=3627 uid=48 gid=48 euid=48 egid=48 suid=48 sgid=48 fsuid=48 fsgid=48 } path1={ uid=0 gid=0 ino=688153 major=8 minor=1 perm=0755 type=file } path1.parent={ uid=0 gid=0 ino=688129 perm=0755 } <kernel> /usr/sbin/httpd /bin/sh file read /bin/cat
最初のログは、 /usr/sbin/httpd
から実行された /bin/sh
から /bin/cat
の実行が要求され、そのときの0番目の引数( argv[0] と呼ばれます)は cat 、1番目の引数( argv[1] と呼ばれます)は /etc/passwd であったことを示しています。このログの1行目に mode=enforcing および granted=no という内容が含まれているため、この要求は拒否されたことが判ります。
2番目のログは、 /usr/sbin/httpd
から実行された /bin/sh
が /bin/cat
を読み込みモードでオープンしようとして拒否されたことを示しています。これは、要求されたプログラムを実行できなかった場合そのプログラムの内容を確認するために読み込みモードでオープンしようとするという習性が /bin/sh
にあるためです。
7.2. 通知デーモン
ポリシー違反の発生を通知するために tomoyo-notifyd
というデーモンプログラムが提供されています。 /etc/rc.local 等から /usr/sbin/tomoyo-notifyd を起動するようにしてください。
通知方法は /etc/tomoyo/tools/notifyd.conf に記録されています。以下に初期設定を示します:
# This file contains configuration used by tomoyo-notifyd command. # tomoyo-notifyd is a daemon that notifies the occurrence of policy violation # in enforcing mode. # # time_to_wait is grace time in second before rejecting the request that # caused policy violation in enforcing mode. For example, if you specify # 30, you will be given 30 seconds for starting tomoyo-queryd command and # responding to the policy violation event. # If you specify non 0 value, you need to register tomoyo-notifyd command to # /sys/kernel/security/tomoyo/manager as well as tomoyo-queryd command, for tomoyo-notifyd needs to # behave as if tomoyo-queryd command is running. # Also, you should avoid specifying too large value (e.g. 3600) because # the request will remain pending for that period if you can't respond. # # action_to_take is a command line you want to use for notification. # The command specified by this parameter must read the policy violation # notification from standard input. For example, mail, curl and xmessage # commands can read from standard input. # This parameter is passed to execve(). Thus, please use a wrapper program # if you need shell processing (e.g. wildcard expansion, environment # variables). # # minimal_interval is grace time in second before re-notifying the next # occurrence of policy violation. You can specify 60 to limit notification # to once per a minute, 3600 to limit notification to once per an hour. # You can specify 0 to unlimit, but notifying of every policy violation # events (e.g. sending a mail) might annoy you because policy violation # can occur in clusters if once occurred. # Please use TOMOYO Linux's escape rule (e.g. '\040' rather than '\ ' for # representing a ' ' in a word). # Examples: # # time_to_wait 180 # action_to_take mail admin@example.com # # Wait for 180 seconds before rejecting the request. # The occurrence is notified by sending mail to admin@example.com # (if SMTP service is available). # # time_to_wait 0 # action_to_take curl --data-binary @- https://your.server/path_to_cgi # # Reject the request immediately. # The occurrence is notified by executing curl command. # time_to_wait 0 action_to_take mail -s Notification\040from\040tomoyo-notifyd root@localhost minimal_interval 60
action_to_take 行を変更して tomoyo-notifyd
を実行してください。
ポリシー違反が発生すると以下のようなメールが届くはずです。このメールの内容は、ヘッダにシリアルナンバーが付与されている点を除いてアクセスログと同一内容です:
Mail version 8.1 6/6/93. Type ? for help. "/var/spool/mail/root": 1 messages 1 new >N 1 root@localhost.local Sun Dec 26 01:08 18/1211 "Notification from tomoyo-notifyd" & Message 1: From root@localhost.localdomain Sun Dec 26 01:08:35 2010 Date: Sun, 26 Dec 2010 01:08:35 +0900 From: root <root@localhost.localdomain> To: root@localhost.localdomain Subject: Notification from tomoyo-notifyd Q0-0 #2010/12/25 16:08:35# profile=3 mode=enforcing granted=no (global-pid=3628) task={ pid=3628 ppid=3627 uid=48 gid=48 euid=48 egid=48 suid=48 sgid=48 fsuid=48 fsgid=48 } path1={ uid=0 gid=0 ino=688153 major=8 minor=1 perm=0755 type=file } path1.parent={ uid=0 gid=0 ino=688129 perm=0755 } exec={ realpath="/bin/cat" argc=2 envc=7 argv[]={ "cat" "/etc/passwd" } envp[]={ "TERM=vt100" "PATH=/sbin:/usr/sbin:/bin:/usr/bin" "_=/bin/cat" "PWD=/usr/share/horde/admin" "LANG=en_US.UTF-8" "SHLVL=3" "LANGUAGE=en_US.UTF-8" } } <kernel> /usr/sbin/httpd /bin/sh file execute /bin/cat
7.3. ポリシー違反を対話的に処理する
強制モードで発生したポリシー違反は、 tomoyo-queryd
を用いることで対話的に処理することができます。この機能は、ソフトウェアアップデート時に便利です。なぜなら、ソフトウェアのアップデートにより、以下の何れかの状況が発生した場合にポリシーを修正する必要が生じる場合があるからです:
- ファイルのパス名が変化した場合
- ファイルの依存関係が変化した場合
- 必要なアクセス許可が変化したり増えたりした場合
学習モードを使ってポリシーを最初から再取得するのが理想です。しかし、一度強制モードでの運用を開始したシステムを強制モード以外に変更することは、アクセスが制限されていないドメインへの攻撃に対してシステム全体が無防備になってしまうため、望ましくありません。
幸いなことに、 tomoyo-queryd
を使うことで、管理者は強制モードでシステムを稼働させた状態のままポリシーの修正を行うことができます。ただし、この方法は、全てのケースに対応できるとは限らず、最適なポリシーであることを保証するものではありません。
7.3.1. tomoyo-queryd の操作例
実際の tomoyo-queryd
の操作手順について以下のムービーで紹介しています。また、以下にテキストでも示します:
ポリシーに違反したアクセス要求を処理するために tomoyo-queryd
コマンドを利用します:
# /usr/sbin/tomoyo-queryd
Monitoring /sys/kernel/security/tomoyo/query . Press Ctrl-C to terminate.
パッケージのアップデート中に、デーモンの再起動などのように普段行われない動作によりポリシー違反が発生するかもしれません。ポリシー違反が発生した場合、 tomoyo-queryd
にプロンプトが表示されます:
#2010/12/30 00:21:11# profile=3 mode=enforcing granted=no (global-pid=11788) task={ pid=11788 ppid=11779 uid=0 gid=0 euid=0 egid=0 suid=0 sgid=0 fsuid=0 fsgid=0 } path1={ uid=0 gid=0 ino=753729 major=253 minor=0 perm=0755 type=file } path1.parent={ uid=0 gid=0 ino=753665 perm=0755 } exec={ realpath="/bin/sleep" argc=2 envc=6 argv[]={ "sleep" "1" } envp[]={ "TERM=xterm" "PATH=/sbin:/usr/sbin:/bin:/usr/bin" "PWD=/" "LANG=en_US.UTF-8" "SHLVL=1" "_=/bin/sleep" } } <kernel> /etc/rc.d/init.d/sshd file execute /bin/sleep Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):
上記の例は、 <kernel> /etc/rc.d/init.d/sshd というドメインに属しているプロセスが sleep 1
というコマンドラインを処理するために /bin/sleep
の実行を要求したが、ポリシーによって拒否されたことを示しています。通常であればポリシーに違反したアクセス要求は直ちに拒否されますが、 tomoyo-queryd
が動作しているため、カーネルはあなたの判断を仰いでいることを示しています:
Y を押すと許可します。
N を押すと拒否します。
R を押すと再試行します。(手作業でドメインポリシーを変更した後などに利用します。)
S を押すとそのプロセスのドメインポリシーが表示します。
A を押すと編集した上でドメイン用ポリシーに追加後、再試行します。(先にドメインポリシーを編集することができます。)
無条件にアクセス要求を許可しないようにしてください。ポリシー違反の原因がパッケージのアップデートによるものとは限らず、侵入者の攻撃によるものである可能性があるからです。
このプログラムが動作している間は、ポリシーによって拒否されたアクセス要求は、あなたが応答するまで永遠に保留状態となりますので、ログアウトしないでください。プログラムが必要とするアクセス許可が与えられるようにするために、出力の監視を忘れないようにしてください。もし、アクセス許可の不足が検出された場合にはプロンプトが表示されます。ポリシーをのアップデートが完了したら、 Ctrl-C を入力して終了させてください。
このプログラムはメモリ上のポリシーを直接編集します。シャットダウンすると失われてしまいますので、忘れずに tomoyo-savepolicy
を実行してポリシーを保存してください。
# /usr/sbin/tomoyo-savepolicy
7.3.2. tomoyo-queryd の出力例
以下は tomoyo-queryd
がどのような出力を行うかの例を示しています:
#2010/12/30 00:21:11# profile=3 mode=enforcing granted=no (global-pid=11788) task={ pid=11788 ppid=11779 uid=0 gid=0 euid=0 egid=0 suid=0 sgid=0 fsuid=0 fsgid=0 } path1={ uid=0 gid=0 ino=753729 major=253 minor=0 perm=0755 type=file } path1.parent={ uid=0 gid=0 ino=753665 perm=0755 } exec={ realpath="/bin/sleep" argc=2 envc=6 argv[]={ "sleep" "1" } envp[]={ "TERM=xterm" "PATH=/sbin:/usr/sbin:/bin:/usr/bin" "PWD=/" "LANG=en_US.UTF-8" "SHLVL=1" "_=/bin/sleep" } } <kernel> /etc/rc.d/init.d/sshd file execute /bin/sleep Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):a Enter new entry> file execute /bin/sleep Added 'file execute /bin/sleep'. ---------------------------------------- #2010/12/30 00:22:12# profile=3 mode=enforcing granted=no (global-pid=11937) task={ pid=11937 ppid=1 uid=26 gid=26 euid=26 egid=26 suid=26 sgid=26 fsuid=26 fsgid=26 } path1={ uid=0 gid=0 ino=690602 major=253 minor=0 perm=0644 type=file } path1.parent={ uid=0 gid=0 ino=690114 perm=0755 } <kernel> /etc/rc.d/init.d/postgresql /sbin/runuser /bin/bash /usr/bin/postmaster file read /usr/share/zoneinfo/posix/Pacific/Pohnpei Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):s # select global-pid=11937 <kernel> /etc/rc.d/init.d/postgresql /sbin/runuser /bin/bash /usr/bin/postmaster use_profile 3 use_group 0 network unix stream connect /var/run/nscd/socket file read /usr/lib/locale/locale-archive file read /var/lib/pgsql/data/postgresql.conf file read /var/lib/pgsql/data/PG_VERSION file read /var/lib/pgsql/data/global/pg_control file write /var/lib/pgsql/data/global/pg_control file create /var/lib/pgsql/data/postmaster.pid 0600 file read /var/lib/pgsql/data/postmaster.pid file write /var/lib/pgsql/data/postmaster.pid file unlink /var/lib/pgsql/data/postmaster.pid file read /usr/share/zoneinfo/MST7MDT (...snipped...) file read /usr/share/zoneinfo/EST5EDT network inet stream bind 127.0.0.1 5432 network inet stream listen 127.0.0.1 5432 file create /tmp/.s.PGSQL.5432.lock 0600 file read /tmp/.s.PGSQL.5432.lock file write /tmp/.s.PGSQL.5432.lock file unlink /tmp/.s.PGSQL.5432.lock file unlink /tmp/.s.PGSQL.5432 network unix stream bind /tmp/.s.PGSQL.5432 network unix stream listen /tmp/.s.PGSQL.5432 file mksock /tmp/.s.PGSQL.5432 0700 file chmod /tmp/.s.PGSQL.5432 0777 file write /var/lib/pgsql/data/postmaster.opts file truncate /var/lib/pgsql/data/postmaster.opts file mkdir /var/lib/pgsql/data/pg_log/ 0700 file append /var/lib/pgsql/data/pg_log/postgresql-Wed.log network inet dgram bind 127.0.0.1 0 file read /var/lib/pgsql/data/pg_hba.conf file read /var/lib/pgsql/data/pg_ident.conf file read /var/lib/pgsql/data/pg_xlog/000000010000000000000000 file write /var/lib/pgsql/data/pg_xlog/000000010000000000000000 file read /var/lib/pgsql/data/pg_clog/0000 file write /var/lib/pgsql/data/pg_clog/0000 file read /var/lib/pgsql/data/pg_multixact/offsets/0000 file write /var/lib/pgsql/data/pg_multixact/offsets/0000 file read /var/lib/pgsql/data/global/pg_fsm.cache file write /var/lib/pgsql/data/global/pg_fsm.cache file unlink /var/lib/pgsql/data/global/pg_fsm.cache file read /var/lib/pgsql/data/global/1262 file write /var/lib/pgsql/data/global/1262 file read /var/lib/pgsql/data/global/1260 file write /var/lib/pgsql/data/global/1260 file read /var/lib/pgsql/data/global/1261 file write /var/lib/pgsql/data/global/1261 file read /var/lib/pgsql/data/global/pg_auth file read /var/lib/pgsql/data/global/pgstat.stat file create /var/lib/pgsql/data/global/pgstat.tmp 0666 file write /var/lib/pgsql/data/global/pgstat.tmp file rename /var/lib/pgsql/data/global/pgstat.tmp /var/lib/pgsql/data/global/pgstat.stat file read /var/lib/pgsql/data/pg_subtrans/0000 file write /var/lib/pgsql/data/pg_subtrans/0000 file create /var/lib/pgsql/data/global/pg_fsm.cache 0666 file create /var/lib/pgsql/data/global/pg_auth.\$ 0666 file create /var/lib/pgsql/data/global/pg_database.\$ 0666 file rename /var/lib/pgsql/data/global/pg_auth.\$ /var/lib/pgsql/data/global/pg_auth file rename /var/lib/pgsql/data/global/pg_database.\$ /var/lib/pgsql/data/global/pg_database file unlink /var/lib/pgsql/data/base/\$/pg_internal.init file write /var/lib/pgsql/data/global/pg_auth.\$ file write /var/lib/pgsql/data/global/pg_database.\$ network inet dgram send 127.0.0.1 1024-65535 #2010/12/30 00:22:26# profile=3 mode=enforcing granted=no (global-pid=11937) task={ pid=11937 ppid=1 uid=26 gid=26 euid=26 egid=26 suid=26 sgid=26 fsuid=26 fsgid=26 } path1={ uid=0 gid=0 ino=690602 major=253 minor=0 perm=0644 type=file } path1.parent={ uid=0 gid=0 ino=690114 perm=0755 } <kernel> /etc/rc.d/init.d/postgresql /sbin/runuser /bin/bash /usr/bin/postmaster file read /usr/share/zoneinfo/posix/Pacific/Pohnpei Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):a Enter new entry> file read /usr/share/zoneinfo/\{\*\}/\* Added 'file read /usr/share/zoneinfo/\{\*\}/\*'. ---------------------------------------- #2010/12/30 00:22:23# profile=3 mode=enforcing granted=no (global-pid=11974) task={ pid=11974 ppid=11968 uid=0 gid=0 euid=0 egid=0 suid=0 sgid=0 fsuid=0 fsgid=0 } path1={ uid=0 gid=0 ino=524564 major=253 minor=0 perm=0644 type=file } path1.parent={ uid=0 gid=0 ino=524555 perm=0755 } <kernel> /usr/sbin/sshd file read /etc/pki/tls/openssl.cnf Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):a Enter new entry> file read /etc/pki/tls/openssl.cnf Added 'file read /etc/pki/tls/openssl.cnf'. ---------------------------------------- #2010/12/30 00:22:53# profile=3 mode=enforcing granted=no (global-pid=11937) task={ pid=11937 ppid=1 uid=26 gid=26 euid=26 egid=26 suid=26 sgid=26 fsuid=26 fsgid=26 } path1.parent={ uid=26 gid=26 ino=426399 perm=0700 } <kernel> /etc/rc.d/init.d/postgresql /sbin/runuser /bin/bash /usr/bin/postmaster file create /var/lib/pgsql/data/pg_log/postgresql-Thu.log 0666 Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):a Enter new entry> file create /var/lib/pgsql/data/pg_log/postgresql-\* Added 'file create /var/lib/pgsql/data/pg_log/postgresql-\*.log 0666'. #2010/12/30 00:23:04# profile=3 mode=enforcing granted=no (global-pid=11937) task={ pid=11937 ppid=1 uid=26 gid=26 euid=26 egid=26 suid=26 sgid=26 fsuid=26 fsgid=26 } path1={ uid=26 gid=26 ino=426434 major=253 minor=0 perm=0600 type=file } path1.parent={ uid=26 gid=26 ino=426399 perm=0700 } <kernel> /etc/rc.d/init.d/postgresql /sbin/runuser /bin/bash /usr/bin/postmaster file append /var/lib/pgsql/data/pg_log/postgresql-Thu.log Allow? ('Y'es/'N'o/'R'etry/'S'how policy/'A'dd to policy and retry):a Enter new entry> file append /var/lib/pgsql/data/pg_log/postgresql-\* Added 'file append /var/lib/pgsql/data/pg_log/postgresql-\*.log'.
7.4. 全てのドメインに対して強制モードを有効にする
これまでに紹介してきた概念を理解しツールを使いこなせるようになれば、システム全体をアクセス制御の対象とするようなポリシーを作成することができることでしょう。全てのドメインを「強制モード」で運用すれば、システムの侵害へとつながるような弱点を減らすのに有効です。 Apache を制限する例で示した手順は、そのまま全てのドメインを制限するために使うことができます。
7.5. おわりに
このガイドのこの章までの内容は、 TOMOYO Linux を設定するのに十分な知識を提供することを狙っています。より深い知識を得るために、この先の章も読んでください。次の章から先は必ずしも不可欠とはいえない応用的な内容ですが、システムのセキュリティを高めるために役に立つことでしょう。このガイドの末尾にある付録、特に仕様についての解説は役に立つことでしょう。
セキュリティ対策が最も弱い場所を狙われるということを忘れないでください。 TOMOYO Linux が提供する強制アクセス制御機能を正しく使うことは、システムが侵害されることへの対策ではありますが、その他のシステムのセキュリティを高めるための手法や実践も忘れないでください。その他のシステムのセキュリティを高めるための手法や実践はこのガイドの対象外ですが、システムのセキュリティを最大限に高めたいと思うのならば真剣に取り組むようにしてください。