LoginSignup
5
4

More than 5 years have passed since last update.

Apacheで cgi-bin 以外のディレクトリにCGIスクリプトを配置する

Posted at

実行環境

  • CentOS Linux release 7.4.1708 (Core)
  • Apache/2.4.6 (CentOS)

ここでは、新しく追加するCGIのディレクトリを /var/www/platform としています。作成するディレクトリに合わせて適宜読み替えてください

ディレクトリの作成

Apacheの実行ユーザーで読み書きができるディレクトリを作成します

# mkdir /var/www/platform
# chmod 775 /var/www/platform
# chown root.apache /var/www/platform

/var/www/cgi-bin と合わせて root.apache にすれば良いと思います

# ls -ld /var/www/cgi-bin /var/www/platform
drwxrwxr-x. 2 root apache 28 12月  5 19:12 /var/www/cgi-bin
drwxrwxr-x. 5 root apache 64 12月  6 13:45 /var/www/platform

Apacheの設定

基本的には Apacheのドキュメント の通りに設定します

/etc/httpd/conf.d に新しく追加するディレクトリの設定を追加します。ここでは /etc/httpd/conf.d/test_platform.conf という名前で新しい設定ファイルを作りましたが、末尾が ".conf" であればどのような名前でも構いません、自分が新たに何の目的で作ったのか分かるような名前にすれば良いと思います

/etc/httpd/conf.d/test_platform.conf

Alias /platform/ /var/www/platform/
<Directory "/var/www/platform">
    AllowOverride None
    Options ExecCGI
    Require method GET POST OPTIONS
    <FilesMatch (\.cgi|^[^\.]+)$>
        Sethandler cgi-script
    </FilesMatch>
</Directory>

この設定で http://%サーバーのアドレス%/platform/ 配下が /var/www/platform/ 内のコンテンツとして配置されます。ここでは platform ディレクトリ内に CGIスクリプトだけでなく、画像やHTMLコンテンツの配置も考えて ScriptAlias ではなく Alias にして Options ExecCGI を設定するようにしています。また、 .cgi の拡張子だけでなく、拡張子のない場合は CGI スクリプトとして動作するようにしています

変更後は、設定を適用させます

# systemctl reload httpd.service

SELinuxの設定

※ SELinuxを無効にしている場合は、この手順は必要ありません

Apacheの設定が完了し、いざcgiを実行しようとすると 503 エラー。ログを見るとスクリプト実行のパーミッション拒否でした

 AH01215: (13)Permission denied: exec of '/var/www/platform/test' failed

もちろんファイルのオーナーや実行権の確認はしています

# ls -l
合計 1
-rwxr-xr-x. 1 apache   apache    71 12月  5 18:42 test

ネットで見ると、SELinuxの動作が疑わしかったのですが、Auditログや ausearch --message AVC コマンドを確認しても拒否された情報が残っていなかったので、Apacheの設定ミスなのかと思ってかなりハマってしまいました。setenforce 0 を実行するとCGIスクリプトが動作するようになったので、SELinuxの設定は必要だったようです。

SELinuxにはファイルパスに対して、どんな目的で利用されるかといったコンテキストを持っていて、その目的以外のアクセスが行われるとブロックする機能があります。その設定は /etc/selinux/targeted/contexts/files/file_contexts にあり、これを見てみると cgi-bin とついた名前のディレクトリに対して httpd_sys_script_exec_t というタイプが設定されるようになってます

$ grep 'cgi-bin' /etc/selinux/targeted/contexts/files/file_contexts
/var/www/[^/]*/cgi-bin(/.*)?    system_u:object_r:httpd_sys_script_exec_t:s0
/var/www/html/[^/]*/cgi-bin(/.*)?       system_u:object_r:httpd_sys_script_exec_t:s0
/usr/lib/cgi-bin(/.*)?  system_u:object_r:httpd_sys_script_exec_t:s0
/var/www/cgi-bin(/.*)?  system_u:object_r:httpd_sys_script_exec_t:s0
/usr/lib/mailman.*/cgi-bin/.*   --      system_u:object_r:mailman_cgi_exec_t:s0
/usr/lib/cgi-bin/(nph-)?cgiwrap(d)?     --      system_u:object_r:httpd_suexec_exec_t:s0
/var/www/cgi-bin/munin.*        system_u:object_r:munin_script_exec_t:s0

         :

新しいCGIのディレクトリにも、このコンテキストを設定すればCGIスクリプトが実行できるようになります。コンテキストの設定には semanage コマンドを使います。ディレクトリ名の後に (/.*)? を付けて、正規表現でディレクトリ自身とその配下に含まれるファイルやサブディレクトリを指すようにします

# semanage fcontext -a -t httpd_sys_script_exec_t '/var/www/platform(/.*)?'
# semanage fcontext -C -l
SELinux fcontext                                   タイプ                コンテキスト

/var/www/platform(/.*)?                            all files          system_u:object_r:httpd_sys_script_exec_t:s0

/etc/selinux/targeted/contexts/files/file_contexts.local が出来上がるので、中を見てみると、新規登録した /var/www/platform が記述されています

実行例

# cat /etc/selinux/targeted/contexts/files/file_contexts.local
# This file is auto-generated by libsemanage
# Do not edit directly.

/var/www/platform(/.*)?    system_u:object_r:httpd_sys_script_exec_t:s0

restorecon コマンドを実行して、ディレクトリに変更したタイプを設定します

# restorecon -v /var/www/platform
restorecon reset /var/www/platform context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:httpd_sys_script_exec_t:s0

※ /var/www 以下ではないディレクトリであれば変更前のタイプは httpd_sys_content_t になってないかもしれません。

httpd_sys_content_t から httpd_sys_script_exec_t に変わったことを確認します。コンテキストの確認には ls コマンドの -Z オプションを使います

ディレクトリ自体のコンテキスト
# ls -dZ /var/www/platform
drwxrwxr-x. root apache unconfined_u:object_r:httpd_sys_script_exec_t:s0 /var/www/platform

ディレクトリ内のファイルのコンテキスト
$ ls -l -Z /var/www/platform/test 
-rwxr-xr-x. apache apache unconfined_u:object_r:httpd_sys_script_exec_t:s0 /var/www/platform/test

これでCGIスクリプトが実行できるようになっているはずです

参考

redhat CUSTOMER PORTAL - 4.6. SELINUX コンテキスト – ファイルのラベル付け
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/sect-security-enhanced_linux-working_with_selinux-selinux_contexts_labeling_files

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4