suEXEC環境への移行


おやじのサーバは、家族以外に開放しているわけでもないのですが、家族が勝手に CGI を置くことと、万が一のことを考え suEXEC 環境に移行することにしました。他人にサーバを貸す場合は、ユーザの利便性を保ちつつセキュリティや事故を防止する方法として WWW サーバを suEXEC 環境で動作させるのは非常に有効です。但し、いくつか制約が出てくるので、現用サーバを移行する場合は、十分テストしてから移行することを薦めます。設定ミスだけではなく、プログラムによっては、切り替えた途端に動作しなくなる場合もありますので注意が必要です。

■suEXEC 機能の概要

通常、CGI や SSI を実行する場合、WWW サーバと同じユーザ ( apache や nobody 等 )で実行されます。 十分に試験された、あるいは広く流通している CGI  ではあまり問題はないでしょうが、ユーザが作成した CGI や SSI を実行した場合、悪意はなくても WWW サーバのユーザ権限が及ぶファイル等が誤って消してしまう等の事故が考えられます。 当然、自分自身で作成する場合も同じようなことが発生しないとも限りません。このような危険を減らしてくれるのが、suEXEC 機能です。
suEXEC 機能を使用すると、Apache ユーザは WWW サーバを実行しているユーザ ID とは 異なるユーザ ID で CGI や SSI を実行することができます。具体的には、ユーザディレクトリで CGI を動作させる場合は、そのユーザ ID で動作するので、他人のファイルを壊すようなことはありません。また、このおかげといってはなんですが、通常モードでは CGI が生成するファイル等は、WWWサーバのユーザ ID ( nobody等 ) になってしまい、一般ユーザ権限では削除や書き換えができないため、削除するとなると管理者が root で代行して削除する等、管理が煩わしくなります。これに対し、suEXEC 環境では、これらのファイルはそのユーザの ID になるので、例えば、FTP で削除したりできるようになり、ユーザにホームディレクトリの管理を任せることが可能になります。

■Apache の suEXEC 化

今回は、Apache2.0.48 を suEXEC 化しました。 Apache の suEXEC 化自体は対して難しい話ではありません。難しく、注意が必要なのは、むしろ環境設定や CGI そのものの作りです。Apache2.0.48 をこちらからダウンロードします。
インストールは、任意の場所にソースを展開してコンパイルします。suEXECは、apacheをコンパイルする際に、オプションを指定することで有効となります。
今回は、suEXEC だけでなく、SSL や DAV を利用できるようにするとともに、PHP を DSO モジュールとして組み込むためのオプションをつけてコンパイルしなおしました。
なお、RedHat9 の場合、の openssl が Kerberos サポートの状態でコンパイルされていて、kerberos のヘッダが何故か /usr/kerberos/include にあるため make でエラーが発生します。下記の赤字のように、ヘッダの場所を明示してあげて下さい。

$ tar zxfv httpd-2.0.48.tar.gz
$ cd httpd-2.0.48

$ export CPPFLAGS=-I/usr/kerberos/include
$ ./configure --enable-ssl \
--enable-dav \
--enable-so \
--enable-suexec \
--with-suexec-caller=apache \
--with-suexec-userdir=public_html \
--with-suexec-docroot=/home \
--with-suexec-logfile=/usr/local/apache2/logs/suexec_log \
--with-suexec-uidmin=500 \
--with-suexec-gidmin=100
$ make clean     # 以前にmake作業した場合のみ
$ make
$ su
# make install


[suEXECコンパイルオプション]
suEXEC のコンパイルオプションを簡単に示します。詳しくは Apache のドキュメントを参照してください。

■Apache の suEXEC 化の確認

インストールが完了したら、Apache を起動して suEXEC 化がうまくなされているか確認します。新規の場合は、あらかじめおやじの HP の他の Apache に関するページと下記を参考にして設定を済ませてください。なお、初めて Apache を触られるなら、いきなり suEXEC 環境でスタートするといろいろな問題にぶつかって行き詰まってしまう恐れもあります。その場合は、suexec を下記のような形で rename しておけば、通常モードで起動するので、こちらで CGI を含めた動作確認をしてから suEXEC 化されると良いでしょう。

# cd /usr/local/apache2/bin
#
mv suexec suexec.bak

Apache がうまく suEXEC 環境で構築できていれば、起動時に Apache のエラーログに下記のようなメッセージが出力されているはずですので確認します。下記で、wrapper 以降に示される suexec のパスはデフォルトのままの場合で、コンパイル時にインストールパスを変更していれば、そのディレクトリになります。


suEXEC mechanism enabled (wrapper: /usr/local/apache2/bin/suexec)

コンパイル時のオプション設定は、下記でも確認できます。

# /usr/local/apache2/bin/suexec -V
 -D AP_DOC_ROOT="/home/"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="apache"
 -D AP_LOG_EXEC="/usr/local/apache2/logs/suexec_log"
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=500
 -D AP_USERDIR_SUFFIX="public_html"

■suEXEC 環境への変更

suEXEC 環境で CG Iを動作させるためには、こちらにあるセキュリティモデルの20項目の条件を満たさなければなりません。条件はいろいろありますが、その中で主に問題となるのは、ディレクトリの構成とCGI 関係のファイルやディレクトリの所有権やパーミッションに関することです。

◆バーチャルホスト環境下での suEXEC 化

おやじのサイトでは、2つのドメインを IP ベースのバーチャルホストで動かしています。一つは、今、ご覧になっているドメイン( ドメイン1: www.aconus.com )で、UserDir を使用した複数ユーザでの運用( http://www.aconus.com/~oyaji/ 等)がメインで、ルートディレクトリはどちらかと言えばおまけで、事実上使用していないに等しいものです。
もう一つは、全く関係ないサイトで、ここでは仮に example.com (ドメイン2 ) とします。このドメインは、逆に UserDir は使用せず、ルートディレクトリでの運用がメインのサイトです。
バーチャルホスト環境下で suEXEC 化する場合、当然、それぞれのバーチャルホストで suEXEC に関する設定が必要になります。
まず最初に問題になるのが、ドキュメントルートの問題です。suEXEC 化した場合、CGI を実行できるのは、コンパイル時に --with-suexec-docroot オプションで指定したドキュメントルート ( /home ) 配下のみになります。また、そのプログラムで「/」で始まったり、「../」等でディレクトリ参照していると、プログラムを実行できません。今まで、おやじの環境では、複数ユーザが使用する ドメイン1では、FTP や UserDir で扱いやすいよう /home をドキュメントルートにし、ドメイン2は単一ユーザ使用のため、/var/www としていました。そのため、suEXEC 化するとドメイン2ではドキュメントルート配下で CGI が動作しなくなりましたので、ドキュメントを /home/example 配下に移動するとともに、バーチャルホストの設定も変更して問題を解決しました。
しかし、ここで新たな問題が発生しました。 suEXEC では、UserDir を除き、CGI の実行権限がコンパイル時に --with-suexec-caller オプションで指定したユーザになってしまい、二つのサイトともドキュメントルート配下では同じユーザ権限 ( apache )になってしまうという問題です。UserDir 環境では suEXEC でセキィリティを確保したのにこれでは片手落ちです。
この問題に関しては、Apache2.0で採用された SuexecUserGroup ディレクティブで解決しました。但し、SuexecUserGroup ディレクティブを使用すると、そのホスト配下の UserDir がここで指定したユーザ権限になってしまうという問題があり、結果として SuexecUserGroup でユーザ/グループを指定すると個別ユーザで CGI が動作しなくなってしまいます。(おやじは未確認ですが、1.3系ではこういうことはないそうです。)  そこで、UserDir を使用するドメイン1のドキュメントルートでは、SuexecUserGroup を使用せず、コンパイル時に指定したユーザ権限で動作させることにし、 UserDir を使用しないドメイン2で SuexecUserGroup ディレクティブを使用してドメイン1と異なる example/users で動作させることにしました。バーチャルホストを使用せず、一ホストで動かす場合は、ドメイン1と同様の対処とすればいいでしょう。
この条件での、httpd.conf の設定( おやじは管理面から、バーチャルホスト関係は vhost.conf として定義し、httpd.conf から include している) を以下に示します。なお、おやじは ssl も使用しているので、ssl.conf のバーチャルホストにも同様の設定をしてあります。ここでは、www.aconus.com用のプライベートアドレスを192.168.1.100、 www.example.com 用を192.168.1.101として説明します。それぞれの設定に関しては、おやじの他のApache関係のコンテンツを参照してください。 suEXEC 環境に移行したたために行った変更部分を赤字で示します。

<VirtualHost 192.168.1.100:80>
  ServerAdmin oyaji@mail.aconus.com
  DocumentRoot "/home/acorn"
  ServerName www.aconus.com

  <Directory "/home/acorn">
    Options FollowSymLinks Includes ExecCGI
    AllowOverride None
    Order allow,deny
    Allow from all
  </Directory>

  UserDir /home/*/public_html
  <Directory /home/*/public_html>
    AllowOverride FileInfo AuthConfig Limit
    Options MultiViews SymLinksIfOwnerMatch ExecCGI IncludesNoExec
    <LimitExcept GET POST OPTIONS PROPFIND>
      Order deny,allow
      Deny from all
    </LimitExcept>
  </Directory>

  ErrorLog logs/error_log
  SetEnvIf Remote_Addr 192.168. homelog nolog
  SetEnvIf Request_URI "~akirin" akirinlog nolog
  SetEnvIf Request_URI "default.ida" wormlog nolog
  SetEnvIf Request_URI "root.exe" wormlog nolog
  SetEnvIf Request_URI "cmd.exe" wormlog nolog
  SetEnvIf Request_URI "Admin.dll" wormlog nolog
  CustomLog logs/home_log common env=homelog
  CustomLog logs/akirin_log combined env=akirinlog
  CustomLog logs/worm_log common env=wormlog
  CustomLog logs/access_log combined env=!nolog
</VirtualHost>

<VirtualHost 192.168.1.101:80>
  ServerAdmin oyaji@mail.aconus.com
  DocumentRoot "/home/example"
  ServerName www.example.com

  SuexecUserGroup example users

  UserDir desable

  <Directory "/home/example">
    Options FollowSymLinks Includes ExecCGI
    AllowOverride None
    Order allow,deny
    Allow from all
  </Directory>

  ErrorLog logs/example.com-error_log
  SetEnvIf Remote_Addr 192.168. homelog nolog
  SetEnvIf Request_URI "default.ida" wormlog nolog
  SetEnvIf Request_URI "root.exe" wormlog nolog
  SetEnvIf Request_URI "cmd.exe" wormlog nolog
  SetEnvIf Request_URI "Admin.dll" wormlog nolog
  CustomLog logs/example.com-home_log common env=homelog
  CustomLog logs/example.com-worm_log common env=wormlog
  CustomLog logs/example.com-access_log combined env=!nolog
</VirtualHost>

◆所有権の設定

suEXEC 環境では、CGI や SSI は指定されたユーザ権限で動作します。従って、CGI や SSI そのものだけでなく、CGI や SSI がアクセスするディレクトリ( ロックフォルダ)や作成されるログファイル等は、全てそのユーザの所有になっていなければなりません。新規の場合は問題にはならないはずですが、既存環境から移行する場合は、前述のようなフォルダやファイルの所有者が apache や nobody になっているはずですので、全てを対象となるユーザに所有権を変更しなければ動作しません。
おやじのコンテンツの例を以下に示します。今までは、Apache のユーザ/グループは、nobody/nobody になっていましたので、これを oyaji/users に変更します。当然ですが、ユーザ毎に変更が必要になります。

# cd /home/oyaji/public_html
# find . -user nobody -print | xargs chown oyaji:users


◆パーミッションの設定

suEXEC 環境では、CGI や SSI のファイルや関連するディレクトリ及びファイルが他のユーザからは書き込める状態では動作しません。指定されたユーザ権限で動作します。従って、CGI や SSI そのものだけでなく、CGI や SSI がアクセスするディレクトリ( ロックフォルダ)や作成されるログファイル等は、全てそのユーザの所有になっていなければなりません。新規の場合は、以下のようにすればよい。なお、CGI 関係以外のファイル( HTML や GIF 等)の扱いは、従来どおり "644" 等としないと見えません。suEXEC はあくまで CGI や SSI の実行に関してのみ機能するものだからです。 既存環境から移行する場合は、前述のようなフォルダやファイルが所有者以外から書き込み可能になっていると CGI や SSI が実行できません。従って、下記により public_html 以下のパーミッションを変更します。

# find /home/*/public_html -perm +022 | xargs chmod go-w

■その他

その他、変更が必要となるものを以下に示します。基本的な設定は、おやじのHPの他の Apache 関係のコンテンツを参考にしてください。
 


Top Pageへ