SELinuxの無効化方法 設定方法 使い方について

SELinuxは強制アクセス制御(MAC:Mandatory access control)とよばれる管理者による権限管理機能を提供する仕組みのひとつです。FISC(金融情報システムセンター)やNISC(内閣官房情報セキュリティセンター)などのガイドラインには強制アクセス制御に関する規定が存在し、もともとは政府の規定を満たすために作成されたのがSELinuxらしいです。

以上の説明やアットマークITのような経営者向けサイトを見ると、SELinuxは、いかにもコンサルタント様が導入を検討しそうな素晴らしい機能ですが、運用を行うのは至難の業です。

以下、私がSELinuxハンズオン – hbstudy #28に参加した時のメモを記します。何となく読んで頂きSELinuxの運用が如何に難しいかを悟って頂けると幸いです。なお、実務でのお役立ち度は期待しないでください。私がSELinuxを勉強して役にたったのはLIPC 303を受験した時くらいです。

当時勉強会で使用されたスライドは、以下を参照ください。

また、SELinuxハンズオン – hbstudy #28を開催頂いた、ishikawa84gさんのサイトは以下を参照ください。

いしかわさん ごめんなさい

SELinuxの無効化

多くの人は、SELinuxの無効化方法と設定確認ができれば充分かと思います。まずは、実務で必要になるレベルのお話をします。

SELinuxの無効化 – OS再起動ができる場合

SELinuxを無効にするには、/etc/sysconfig/selinux(実態は/etc/selinux/configへのシンボリックリンク)をエディタで開き、SELINUX=の部分を”enforcing”から”disabled”に変更します。

diff --git a/selinux/config b/selinux/config
index 29808ee..8237483 100644
--- a/selinux/config
+++ b/selinux/config
@@ -3,7 +3,7 @@
 #      enforcing - SELinux security policy is enforced.
 #      permissive - SELinux prints warnings instead of enforcing.
 #      disabled - SELinux is fully disabled.
-SELINUX=enforcing
+SELINUX=disabled
 # SELINUXTYPE= type of policy in use. Possible values are:
 #      targeted - Only targeted network daemons are protected.
 #      strict - Full SELinux protection.

設定を反映させるために、OSを再起動します。以上でSELinuxの無効化が完了しました。

# reboot

SELinuxの無効化 – OS再起動ができない場合

OS再起動はできないけど、SELinuxが有効になっていて困っている。そんな要望もあるかと思います。

結論から言えば「OS再起動なしにSELinuxを無効化する事はできない」ですが、SELinuxをpermissiveモードにする事で問題を回避できると思います。permissiveモードは、権限違反時に拒否を行わずログ出力のみを行うモードです。permissiveモードにしておけば、「権限不足であれが動かない」と言った悩みを解決できるはずです。

SELinuxの状態確認

想定する動作をしない場合、SELinuxが有効化どうかを確認します。注意して頂きたいのは、/etc/sysconfig/selinuxを見ても確認にはならない事です。SELinuxは設定反映には再起動が必要なので、設定ファイルを見ても確認作業, トラブルの切り分けにはなっていない事に注意して下さい。

今、SELinuxが有効であるかどうはgetenforceというコマンドを使用します。もし、Enforcingと表示されれば有効である事を意味し、”Disabled”と表示されれば無効である事を意味します。

[root@localhost ~]# getenforce
Enforcing
[root@localhost ~]#

SELinuxの設定

これ以降がSELinuxハンズオン – hbstudy#28参加時のメモです。勉強会当時はFedora16によるハンズオンでしたが、2014年10月にCentSO 6.5仕様になるよう一部加筆変更しております。

SELinux 設定ファイル

OSは起動時に”/etc/selinux/config”というファイルを読み込み、SELinuxのstate, typeを決定します。初期設定は以下の通りです。(初期設定はOSバージョンやディストリビューションによって異なります。また一部クラウド事業者はユーザビリティに配慮して、自動的にSELinuxを無効化してくれる事業者もあります。)

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

SELINUXはSELinux stateを決定するパラメータで、SELINUXTYPEはSELinux typeを決定するパラメータです。各パラメータに設定できる値は以下の通りです。

SELINUX指定可能パラメタ意味
enforcingselinuxのポリシーに反する動作を全て拒否します
permissiveselinuxのポリシーに反する動作に対し警告のログを出力します
disabledselinuxを無効化します
SELINUXTYPE指定可能パラメタ意味
targeteddhcpd, httpdなどの代表的なデーモンのみが制御対象となります
strict全てのデーモンが制御対象となります
MLS上記にRBAC(ロールベースアクセス制御)を追加し、strictよりも厳格な動作をします

“/etc/selinux/config”を書き換える事でSELinux stateを変更できますが、setenforceコマンドを使用する事でも、OS再起動なしにSELinux stateを変更できます。引数にpermissive (または0), enforce (または1)を与える事でstateを指定する事ができます。

但し、setenforceコマンドでSELinux stateをdisableにする事はできません。disableに変更するためには”/etc/selinux/config”を書き換えた後に、OS再起動が必要になります

実行例は以下の通りです。

[root@localhost ~]# setenforce 1

設定確認を行うにはgetenforce, sestatusなどのコマンドを使用します。

[root@localhost ~]# getenforce
Enforcing
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# sestatus
selinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
Current mode:                   enforcing
Mode from config file:          enforcing
Policy version:                 26
Policy from config file:        targeted
[root@localhost ~]#

SELinuxの無効化

そもそも、SELinuxは政府機関や金融機関からの厳格なセキュリティ要求を満たすために開発された機能です。政府機関や金融機関からのよっぽどの強い要望がない限りは無効化をお勧めします殆どの場合は、守るべき情報資産の価値よりもメンテナンスコストの方が大きくなってしまいます。

SELinuxを無効にするためには、”/etc/selinux/config”のSELINUXパラメータをdisableに変更する事で対応できます。

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

SELinuxの有効化

SELinuxを無効の状態から有効の状態に変更するには、注意が必要です。必ずpermissive modeにしてからOSを一度再起動する事をお勧めします。OS起動に必要な権限が与えられておらず、OS起動ができなくなってしまう恐れがあるからです。

permissive modeでOS再起動を行ったら、SELinuxのポリシー違反がない事を確認後にenforce modeに変更します。ポリシー違反は”/var/log/audit/audit.log”または”/var/log/messages”にdeniedと記載されます。ログファイルをdeniedでgrepする事で、ポリシー違反がない事を確認できます。

[root@localhost ~]# grep denied /var/log/audit/audit.log /var/log/messages
[root@localhost ~]#

万が一、SELinuxによってOSが起動できなくなった場合は、以下のようにGRUBの画面で起動パラメータに”selinux=0″を与える事で、SELinuxが無効の状態で起動させる事ができます。

selinux_grub

先ほど「必ずpermissiveモードにしてからOSを一度再起動する」事をお勧めしましたが、OSバージョンやディストリビューションによっては、permissiveモードのログ出力が機能しない事もあります。少なくとも、私が動作確認したCentOS 6.5 64bitのpermissiveモードでは、/var/log/messagesにも/var/log/audit/audit.logにもポリシー違反のログ出力は見当たりませんでした。

SELinux 動作概要

セキュリティポリシー

SELinuxはセキュリティポリシーで定義された動作のみを許可します。明示的に許可されていない動作は全て禁止されます (“ホワイトリスト指定”, “暗黙のdeny all”と同じ考え方です)。

セキュリティポリシーは、“誰が(Subject)” “何に(Object)” “何をできるか(Action)”の集合です。例えば、以下は”Webサーバが、HTML文書を、読み込める”というポリシーになります。

allow httpd_t http_sys_content_t : file { read } ;

実際のセキュリティーポリシーは、sesearchというコマンドで調べる事ができます。seseachはsetools-consoleというパッケージ内に含まれていますでの、yumなどでインストールして下さい。

# yum install setools-console

seseachの使用例は以下の通りです。なお、大かっこ ( “[“, “]” )で囲まれた部分はBooleanと呼ばれる値で、この値が真か偽かによってアクセス権を制御する変数です。

[root@localhost ~]# sesearch -A -C -s httpd_t -t httpd_sys_content_t -c file
Found 3 semantic av rules:
   allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ;
ET allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open } ; [ httpd_builtin_scripting ]
ET allow httpd_t httpdcontent : file { ioctl read write create getattr setattr lock append unlink link rename execute open } ; [ httpd_enable_cgi httpd_unified && httpd_builtin_scripting && ]

[root@localhost ~]#

セキュリティコンテキスト

SELinuxでは、ファイル・プロセス・ソケットなどあらゆるリソースに対してセキュリティコンテキストと呼ばれるアクセス可否を判断する属性が付与されています。このセキュリティコンテキストを確認するためには、ls, ps, idなどの一般的なコマンドに-Zオプションを付ける事で確認できます。

[root@localhost ~]# ps -Z
LABEL                             PID TTY          TIME CMD
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 1332 pts/1 00:00:00 bash
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 1346 pts/1 00:00:00 ps
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# ls -aZ
dr-xr-x---. root root system_u:object_r:admin_home_t:s0 .
dr-xr-xr-x. root root system_u:object_r:root_t:s0      ..
-rw-------. root root system_u:object_r:admin_home_t:s0 .bash_history
-rw-r--r--. root root system_u:object_r:admin_home_t:s0 .bash_logout
-rw-r--r--. root root system_u:object_r:admin_home_t:s0 .bash_profile
-rw-r--r--. root root system_u:object_r:admin_home_t:s0 .bashrc
-rw-r--r--. root root system_u:object_r:admin_home_t:s0 .cshrc
drwxr-----. root root system_u:object_r:admin_home_t:s0 .pki
drwx------. root root system_u:object_r:ssh_home_t:s0  .ssh
-rw-r--r--. root root system_u:object_r:admin_home_t:s0 .tcshrc
-rw-------. root root system_u:object_r:admin_home_t:s0 .viminfo
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[root@localhost ~]#

セキュリティコンテキストはセミコロン区切りで4つのフィールドに分かれます。各フィールドの意味は、右から順に以下の通りです。なお、この中で最もトラブル対応で役立つのは、”タイプ属性”です。初学者は、最低限”タイプ属性”だけは覚えておくようにすると良いと思います。

属性意味
ユーザ属性system_uサブジェクトやオブジェクトに割り当てるSELinuxのユーザID
ロール属性object_rユーザに割り当てる権限の範囲を定義したもの。ロールが不要なオブジェクトにはダミーロール(object_r)が付与されます。
タイプ属性admin_home_tSELinuxがアクセス可否を判定する時に使用するセキュリティ属性
機密ラベルs0組織・役職などで分ける識別子

trouble shoot セキュリティコンテキストの再割当

以下、apacheがインストールされている前提で話を進めます。apache, iptablesなどの設定については、説明を省略します。

トラブル概要

以下の手順でindex1.htmlとindex2.htmlを公開します。

# echo 'It Works!' > /var/www/html/index1.html
# echo 'It Works!' > ~/index2.html
# mv ~/index2.html /var/www/html/index2.html

curl, wgetなどで動作確認を行うと、index1.htmlは正常に応答しますがindex2.htmlは403エラーを返します。この403エラーの原因についてトラブルシュートを行います。

[root@localhost ~]# curl -I http://localhost/index1.html
HTTP/1.1 200 OK
Date: Sun, 19 Oct 2014 06:28:50 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Sun, 19 Oct 2014 06:28:04 GMT
ETag: "e01d6-a-505c0b362053c"
Accept-Ranges: bytes
Content-Length: 10
Connection: close
Content-Type: text/html; charset=UTF-8

[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# curl -I http://localhost/index2.html
HTTP/1.1 403 Forbidden
Date: Sun, 19 Oct 2014 06:28:57 GMT
Server: Apache/2.2.15 (CentOS)
Connection: close
Content-Type: text/html; charset=iso-8859-1

[root@localhost ~]#

切り分け

一番最初にやるべき切り分けは、SELinuxによる権限不足なのか、それ以外の問題なのかの切り分けです。permissiveモードに変更して想定通りの動作をするか否かで、SELinuxなのかそれ以外なのかを判別します。

[root@localhost ~]# setenforce permissive
[root@localhost ~]# getenforce
Permissive
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# curl -I http://localhost/index2.html
HTTP/1.1 200 OK
Date: Sun, 19 Oct 2014 06:38:04 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Sun, 19 Oct 2014 06:28:10 GMT
ETag: "180f37-a-505c0b3bd8704"
Accept-Ranges: bytes
Content-Length: 10
Connection: close
Content-Type: text/html; charset=UTF-8

[root@localhost ~]#

permissive modeにすると正常応答するので、SELinuxによってアクセスが拒否されている事が推測できます。

セキュリティコンテキスト 再割当

SELinuxのログを確認します。/var/www/html/index2.htmlに対して、getattr, readなどのシステムコールが許可されていない事が読み取れます。

さらに詳しくログを読み解きます。scontext, tcontextは、それぞれソース・ターゲットのセキュリティコンテキストを表します。つまり、”root:system_r:httpd_t:s0″が”root:object_r:user_home_t:s0″に対して、getattr, readできない旨を表しています。

[root@localhost ~]# grep denied /var/log/messages
Oct 19 15:46:46 skr145 kernel: type=1400 audit(1413701206.718:3): avc:  denied  { getattr } for  pid=1204 comm="httpd" path="/var/www/html/index2.html" dev=vda3 ino=1576759 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file
Oct 19 15:46:46 skr145 kernel: type=1400 audit(1413701206.718:4): avc:  denied  { read } for  pid=1204 comm="httpd" name="index2.html" dev=vda3 ino=1576759 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file
Oct 19 15:46:46 skr145 kernel: type=1400 audit(1413701206.718:5): avc:  denied  { open } for  pid=1204 comm="httpd" name="index2.html" dev=vda3 ino=1576759 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file
[root@localhost ~]#

/var/www/html配下のファイルのセキュリティコンテキストを確認します。index1.htmlのユーザ属性はhttpd_sys_content_tなのでhttpdから読取可能ですが、index2.htmlのユーザ属性はuser_home_tなのでhttpdから読取不可である事が分かりました。

[root@localhost ~]# ls -lZ /var/www/html/
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index1.html
-rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 index2.html
[root@localhost ~]#

セキュリティコンテキストは、どのディレクトリにファイルが作成されたかによって自動的に作成されます。ファイルを移動した場合は、セキュリティコンテキストの再割当をする事によって対応が可能です。restorecon コマンドを使用する事でセキュリティコンテキストの再割当ができます。

[root@localhost ~]# restorecon -RF /var/www/html
[root@localhost ~]# ls -lZ /var/www/html/
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index1.html
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index2.html
[root@localhost ~]#

SELinux有効後に、index2.htmlにアクセス可能になった事を確認します。

[root@localhost ~]# setenforce enforcing
[root@localhost ~]# curl -I http://localhost/index2.html
HTTP/1.1 200 OK
Date: Sun, 19 Oct 2014 07:01:43 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Sun, 19 Oct 2014 06:28:10 GMT
ETag: "180f37-a-505c0b3bd8704"
Accept-Ranges: bytes
Content-Length: 10
Connection: close
Content-Type: text/html; charset=UTF-8

[root@localhost ~]#

trouble shoot booleanの編集

トラブル概要

httpdにおいて、ユーザディレクトリを許可します。/etc/httpd/conf/httpd.confをエディタで開き、”UserDir disabled”をコメントアウトし、さらに”UserDir public_html”のコメントアウトを外します。

diff --git a/httpd/conf/httpd.conf b/httpd/conf/httpd.conf
index d87a326..6f9e052 100644
--- a/httpd/conf/httpd.conf
+++ b/httpd/conf/httpd.conf
@@ -363,14 +363,14 @@ DocumentRoot "/var/www/html"
     # of a username on the system (depending on home directory
     # permissions).
     #
-    UserDir disabled
+    #UserDir disabled

     #
     # To enable requests to /~user/ to serve the user's public_html
     # directory, remove the "UserDir disabled" line above, and uncomment
     # the following line instead:
     #
-    #UserDir public_html
+    UserDir public_html

 </IfModule>

設定反映のために、httpdの再起動を行います。

# /etc/init.d/httpd restart

sampleユーザを作成し、公開ディレクトリにindex.htmlを配布します。

[root@localhost ~]# useradd sample
[root@localhost ~]# su - sample
[sample@localhost ~]$ mkdir ~/public_html
[sample@localhost ~]$ echo 'It works!' > ~/public_html/index.html
[sample@localhost ~]$ chmod -R a+x /home/sample

しかし、index.htmlの取得を試みると、403エラーを返されます。このエラーの原因について考察します。

[sample@localhost ~]$ curl -I http://localhost/~sample/index.html
HTTP/1.1 403 Forbidden
Date: Sun, 19 Oct 2014 07:07:18 GMT
Server: Apache/2.2.15 (CentOS)
Connection: close
Content-Type: text/html; charset=iso-8859-1

[sample@localhost ~]$

切り分け

切り分けを行うために、一時的にpermissive modeに変更します。permissive modeでは正常応答を返す事から、SELinuxによってアクセスが拒否されている事が推測できます。

[root@localhost ~]# setenforce permissive
[root@localhost ~]# curl -I http://localhost/~sample/index.html
HTTP/1.1 200 OK
Date: Sun, 19 Oct 2014 07:08:58 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Sun, 19 Oct 2014 07:06:27 GMT
ETag: "2c000e-a-505c13ca04610"
Accept-Ranges: bytes
Content-Length: 10
Connection: close
Content-Type: text/html; charset=UTF-8

[root@localhost ~]#

エラー原因の確認

エラーの原因を確認するためenforcing modeに戻します。余計なログを排除するために一度”/var/log/messages”を消します。その後、curlコマンドを実行し、エラーログを出力させます。

[root@localhost ~]# setenforce enforcing
[root@localhost ~]# echo "" > /var/log/messages
[root@localhost ~]# curl -I http://localhost/~sample/index.html
HTTP/1.1 403 Forbidden
Date: Sun, 19 Oct 2014 07:33:44 GMT
Server: Apache/2.2.15 (CentOS)
Connection: close
Content-Type: text/html; charset=iso-8859-1

[root@localhost ~]#

ログを確認します。”system_r:httpd_t”が”user_home_dir_t”に対して、seach, getattrする権利がない事が分かりました。

[root@localhost ~]# grep denied /var/log/messages
Oct 19 16:33:44 localhost kernel: type=1400 audit(1413704024.639:25): avc:  denied  { search } for  pid=1354 comm="httpd" name="sample" dev=vda3 ino=2883593 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir
Oct 19 16:33:44 localhost kernel: type=1400 audit(1413704024.639:26): avc:  denied  { getattr } for  pid=1354 comm="httpd" path="/home/sample" dev=vda3 ino=2883593 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_dir_t:s0 tclass=dir
[root@localhost ~]#

“system_r:httpd_t”が”user_home_dir_t”に対して”何ができるか”を確認します。ポリシーを表示されるには、以下のようにsesearchコマンドを実行して下さい。実行結果から、search, getattrが認められるかどうかは、”httpd_enable_homedirs”, “httpd_read_user_content”のboolean次第である事が分かります。

[root@localhost ~]# sesearch -A -C -s httpd_t -t user_home_dir_t -c dir
Found 2 semantic av rules:
DT allow httpd_t user_home_dir_t : dir { ioctl read getattr lock search open } ; [ httpd_enable_homedirs ]
DT allow httpd_t user_home_dir_t : dir { ioctl read getattr lock search open } ; [ httpd_read_user_content httpd_builtin_scripting && ]

[root@localhost ~]#

boolean の変更

booleanの値を書きかえるには、setseboolというコマンドを使用します。boolean書き換え後、curlで200番応答が返る事を確認します。

なお、以下の設定はOS再起動時に消えてしまいます。OS再起動後も設定を反映させたい場合は、setseboolオプションに-Pオプションを付けて下さい。

[root@localhost ~]# setsebool httpd_enable_homedirs 1
[root@localhost ~]# setsebool httpd_read_user_content 1
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# curl -I http://localhost/~sample/index.html
HTTP/1.1 200 OK
Date: Sun, 19 Oct 2014 07:38:25 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Sun, 19 Oct 2014 07:06:27 GMT
ETag: "2c000e-a-505c13ca04610"
Accept-Ranges: bytes
Content-Length: 10
Connection: close
Content-Type: text/html; charset=UTF-8

[root@localhost ~]#

trouble shoot セキュリティポリシーの作成

トラブル概要

/wwwをDocumentRootとして公開し、index.htmlを作成します。まず、/etc/httpd/conf/httpd.confの設定を以下のように書き換えDocumentRootを変更します。

diff --git a/httpd/conf/httpd.conf b/httpd/conf/httpd.conf
index 6f9e052..510b2ec 100644
--- a/httpd/conf/httpd.conf
+++ b/httpd/conf/httpd.conf
@@ -289,7 +289,7 @@ UseCanonicalName Off
 # documents. By default, all requests are taken from this directory, but
 # symbolic links and aliases may be used to point to other locations.
 #
-DocumentRoot "/var/www/html"
+DocumentRoot "/www"

 #
 # Each directory to which Apache has access can be configured with respect

httpd再起動により設定を反映させます。

# /etc/init.d/httpd restart

DocumentRootである/wwwに、index.htmlを作成します。

[root@localhost ~]# mkdir /www
[root@localhost ~]# echo 'It works!' > /www/index.html
[root@localhost ~]# chmod -R 777 /www

この状態で、index.htmlの取得を試みると403エラーが返されます。この原因について考察します。

[root@localhost ~]# curl -I http://localhost/index.html
HTTP/1.1 403 Forbidden
Date: Sun, 19 Oct 2014 07:46:23 GMT
Server: Apache/2.2.15 (CentOS)
Connection: close
Content-Type: text/html; charset=iso-8859-1

[root@localhost ~]#

切り分け

切り分けを行うために、一時的にpermissive modeに変更します。permissive modeでは正常応答を返す事から、SELinuxによってアクセスが拒否されている事が推測できます。

[root@localhost ~]# setenforce permissive
[root@localhost ~]# curl -I http://localhost/index.html
HTTP/1.1 200 OK
Date: Sun, 19 Oct 2014 07:47:45 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Sun, 19 Oct 2014 07:46:01 GMT
ETag: "320002-a-505c1ca260a2e"
Accept-Ranges: bytes
Content-Length: 10
Connection: close
Content-Type: text/html; charset=UTF-8

[root@localhost ~]#

エラー原因の確認

エラーの原因を確認するためenforcing modeに戻します。その後、curlコマンドを実行し、エラーログを出力させます。

[root@localhost ~]# setenforce enforcing
[root@localhost ~]# echo "" > /var/log/messages
[root@localhost ~]# curl -I http://localhost/index.html
HTTP/1.1 403 Forbidden
Date: Sun, 19 Oct 2014 07:50:14 GMT
Server: Apache/2.2.15 (CentOS)
Connection: close
Content-Type: text/html; charset=iso-8859-1

[root@localhost ~]#

ログを確認します。”system_r:httpd_t”が”default_t”に対して、getattrする権利がない事が分かりました。ここで登場するタイプ”default_t”とは、特殊なタイプでマッチするポリシーが存在しない事を意味します。

[root@localhost ~]# grep denied /var/log/audit/audit.log
Oct 19 16:50:14 localhost kernel: type=1400 audit(1413705014.676:40): avc:  denied  { getattr } for  pid=1535 comm="httpd" path="/www/index.html" dev=vda3 ino=3276802 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file
Oct 19 16:50:14 localhost kernel: type=1400 audit(1413705014.676:41): avc:  denied  { getattr } for  pid=1535 comm="httpd" path="/www/index.html" dev=vda3 ino=3276802 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file
[root@localhost ~]#

ダメ押しの意味も込めて、sesearchコマンドでも該当するポリシーが存在しない事を確認します。

[root@localhost ~]# sesearch -A -C -s httpd_t -t default_t -c file

[root@localhost ~]#

セキュリティポリシーの作成

“http_d”は”httpd_sys_content_t”に対して、read, getattrする事ができます。従って、/www配下に作成されたファイルに対してユーザ属性”httpd_sys_content_t”を付与するようセキュリティポリシーを編集します。

セキュリティポリシーはsemanageコマンドを使用して編集します。semanageはpolicycoreutils-pythonパッケージに含まれていますので、以下の要領でpolicycoreutils-pythonをインストールして下さい。

# yum install policycoreutils-python

semanageコマンドを用いてセキュリティポリシーを作成します。その後、セキュリティコンテキストを再割当するためにrestoreconコマンドを実行します。curlで200番応答が返ってくる事を確認して下さい。

[root@localhost ~]# semanage fcontext -a -t httpd_sys_content_t "/www/.*"
[root@localhost ~]# restorecon -RF /www
[root@localhost ~]# curl -I http://localhost/index.html
HTTP/1.1 200 OK
Date: Sun, 19 Oct 2014 08:09:29 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Sun, 19 Oct 2014 07:46:01 GMT
ETag: "320002-a-505c1ca260a2e"
Accept-Ranges: bytes
Content-Length: 10
Connection: close
Content-Type: text/html; charset=UTF-8

[root@localhost ~]#

セキュリティポリシーの自動生成

設定削除

/var/log/audit/audit.logからセキュリティポリシーを作成するのが、非常に困難な場合もあります。そのような場合、最終手段として、audit.logからセキュリティポリシーを自動生成する手法もあります。(但し、許可してはいけないポリシーを許可してしまうリスクは非常に高い事を留意ください)

以前の手順で作成したセキュリティポリシーを自動生成する手法を紹介します。まず、以前の手順で投入したセキュリティポリシーを削除します。

[root@localhost ~]# semanage fcontext -d -t httpd_sys_content_t "/www/.*"
[root@localhost ~]# restorecon -RF v /www

ログの生成

不要なログを削除した後に、audit.logにエラーログを記録させます。

[root@localhost ~]# echo "" > /var/log/messages
[root@localhost ~]# curl -I http://localhost/index.html
HTTP/1.1 403 Forbidden
Date: Sun, 19 Oct 2014 08:14:07 GMT
Server: Apache/2.2.15 (CentOS)
Connection: close
Content-Type: text/html; charset=iso-8859-1

[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# cat /var/log/messages

Oct 19 17:14:07 localhost kernel: type=1400 audit(1413706447.388:44): avc:  denied  { getattr } for  pid=1537 comm="httpd" path="/www/index.html" dev=vda3 ino=3276802 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=system_u:object_r:default_t:s0 tclass=file
Oct 19 17:14:07 localhost kernel: type=1400 audit(1413706447.388:45): avc:  denied  { getattr } for  pid=1537 comm="httpd" path="/www/index.html" dev=vda3 ino=3276802 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=system_u:object_r:default_t:s0 tclass=file
[root@localhost ~]#

セキュリティポリシーの生成

audit.logからセキュリティポリシーを生成するには、audit2allowコマンドを使用します。-mでポリシー名を指定しますが、ポリシー名は重複しない名前ならば特に指定はありません。生成されたポリシーは語尾が.teで終わるファイルに出力して下さい。その後、以下の要領でコンパイルし、local.ppというファイルが作成された事を確認します。

[root@localhost ~]# audit2allow -R -i /var/log/messages -m local > local.te
[root@localhost ~]# make -f /usr/share/selinux/devel/Makefile
Compiling targeted local module
/usr/bin/checkmodule:  loading policy configuration from tmp/local.tmp
/usr/bin/checkmodule:  policy configuration loaded
/usr/bin/checkmodule:  writing binary representation (version 10) to tmp/local.mod
Creating targeted local.pp policy package
rm tmp/local.mod.fc tmp/local.mod
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# ls -l
total 72
-rw-r--r--. 1 root root     0 Oct 19 17:15 local.fc
-rw-r--r--. 1 root root    23 Oct 19 17:15 local.if
-rw-r--r--. 1 root root 60928 Oct 19 17:15 local.pp
-rw-r--r--. 1 root root   128 Oct 19 17:15 local.te
drwxr-xr-x. 2 root root  4096 Oct 19 17:15 tmp
[root@localhost ~]#

セキュリティポリシーの読込

セキュリティポリシーを読み込むにはsemoduleコマンドを用います。-iオプションがインストール、-lオプションが一覧表示、-Rオプションがリストアです。。

以下のようにコマンドを実行し、local.ppというファイルを元にセキュリティポリシーをインストールします。その後、”semodule -l”でインストールが完了している事を確認します。

[root@localhost ~]# semodule -i local.pp
[root@localhost ~]# semodule -l | grep local
local   1.0
[root@localhost ~]#

“semodule -R”でインストールしたセキュリティポリシーをリストアします。

[root@localhost ~]# semodule -R

最後に、curlコマンドを用いて200番応答が返る事を確認します。

[root@localhost ~]# curl -I http://localhost/index.html
HTTP/1.1 200 OK
Date: Sun, 19 Oct 2014 08:22:39 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Sun, 19 Oct 2014 07:46:01 GMT
ETag: "320002-a-505c1ca260a2e"
Accept-Ranges: bytes
Content-Length: 10
Connection: close
Content-Type: text/html; charset=UTF-8

[root@localhost ~]#

 

Tips

SELinuxのログ出力先

SELinuxのログ出力先は、OSバージョンやディストリビューションによって異なります。多くの場合は、/var/log/audit/audit.logか/var/log/messagesかのどちらかでしょう。

検証用途で扱いやすいCentOSですが、これは/var/log/messagesにログ出力されるため、SELinuxの勉強には向いていません。

/var/log/audit/audit.logにポリシー違反を出力してもらった方が、何かと読みやすいと思います。ですので、SELinuxの勉強をするならば/var/log/audit/audit.logにログ出力するFedoraをお勧めします。

動作確認環境

勉強会当時の動作確認環境は以下の通りです。勉強会で使用するSELinuxの機能が安定して動作するという事で、fedora16によるハンズオンを開催しております。

  • 動作確認日 2011/12/09
  • fedora 16

後日、CentOS 6.5による動作確認を行いましたが、ログ出力の挙動がFedora 16と異なる事が確認できました。CentOSのログ出力は扱いづらかったので、学習用途ならばCentOSよりもFedoraをお勧めします。

  • 動作確認日 : 2014/10/19
  • CentOS 6.5
タイトルとURLをコピーしました