事象
パーミッション設定は 777 になっているのに、Apache や Nginx で 403 forbidden が表示される。
原因
RedHat 系なら SELinux , Debian (Ubuntu 含む) 系なら AppArmor が有効になっていて、かつ、表示されないファイルのコンテキスト(SELinux/AppArmor におけるアクセス権) が適切な値になっていない。
原因詳細
SELinux , AppArmor は、通常の xfs/ext4 等で使われるアクセス権 (パーミッション) ではカバーしきれないセキュリティを提供する機能です。バッファオーバーフロー攻撃等でプロセスが乗っ取られた際に、被害の範囲を限定することができるのが、SELinux/AppArmor の主なメリットです。
例えば SELinux を有効にしている場合、httpd というプロセスは [httpd_sys_content_t] 等の特定のコンテキストが無いとアクセスができません。なので、例えば postfix プロセスが乗っ取られた場合は、この[httpd_sys_content_t] というラベルのつけられたファイルにアクセスすることはできません。
この SELinux のコンテキストは、NSA および Linux のディストリビュータが「こういった設定が望ましい」というポリシーを記載したファイルを同梱しており、それに基づいて自動的に付与されます。
ただし、SELinux を有効化する前に作ったファイルや、どこかで作成したファイルを移動 (cp ではなく mv) してきた場合、はたまた、プロセスユーザが想定していないディレクトリにファイルを作った場合 (例えば Apache で DocumentRoot を /temporary/ 等に指定した場合) などは、このコンテキストが正しく付与されない場合があります。
解決方法
解決方法1. (RedHat系の場合) SELinux を無効化する
まず SELinux が有効化になっているかを確認します。
# getenforce
このコマンドの結果、 "Enforcing" が返ってきた場合は SELinux が有効になっていますので、以下コマンドで一時的に無効化します。
# setenforce 0
再起動後も恒久的に SELinux を無効化し続けたい場合は、/etc/selinux/config を以下のように変更します。
SELINUX=enforcing
と書かれている箇所を
SELINUX=disabled
に修正します。
解決方法1. (Debian/Ubuntu 系の場合) AppArmor を無効化する
まずは AppArmor が有効化されているか確認します。
systemctl status apparmor
以下で一時的に無効化します。(再起動すると有効化に戻ります。)
systemctl stop apparmor
以下で再起動後も恒久的に無効化します。
systemctl disable apparmor
解決方法2. 該当ディレクトリに適切なコンテキストを設定する
例えば /temporary/ を DocumentRoot にした場合、以下コマンドでこのディレクトリおよび配下のディレクトリ・ファイルに httpd_sys_content_t を付与します。
現状どのコンテキストが割り当たっているかを確認するには、lsコマンドに-Zオプションを使います。
付与する方法も一時的に付与する方法と、永続的(再起動後も有効)に付与する方法があります。
一時的に付与する場合は、chcon コマンドを使います。
-Rは再帰的に/temporary配下のディレクトリ・ファイルにも適用するオプション、-t は付与したいコンテキストのタイプを指定するためのオプションです。
永続的に付与する場合は、semanage コマンドで定義ファイルを書き換えた後、restorecon コマンドで定義ファイルの適用を行います。
# restorecon -RF /temporary
restorecon コマンドを使うと、chcon で適用した内容は破棄されます。
コメント