Google

NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.7">

第 22 章 セーフモード

PHPのセーフモードは共有サーバでのセキュリティの問題を解決するための 試みです。この問題をPHPのレベルで解決しようとするのはアーキテクチャ上 正しくありません。しかし、WebサーバやOSレベルでの代替策はあまり現実 てきではないため、多くのユーザ、特にISPではセーフモードが現在使用され ています。

セーフモードを制御する設定ディレクティブには、次のようなものがあります。
safe_mode = Off 
open_basedir = 
safe_mode_exec_dir = 
safe_mode_allowed_env_vars = PHP_ 
safe_mode_protected_env_vars = LD_LIBRARY_PATH 
disable_functions =

セーフモードがonの場合、PHPは、 現在のスクリプトの所有者がファイル関数により処理されているファイル の所有者に一致するかどうかを調べます。例えば、
-rw-rw-r--    1 rasmus   rasmus       33 Jul  1 19:20 script.php 
-rw-r--r--    1 root     root       1116 May 26 18:01 /etc/passwd
以下のscript.php を実行すると、
<?php
 readfile('/etc/passwd'); 
?>
セーフモードが有効な場合、以下のようなエラーが出力されます。
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not 
allowed to access /etc/passwd owned by uid 0 in /docroot/script.php on line 2

safe_modeの代わりに、 open_basedirディレクトリを設定すると、 指定したディレクトリでの全てのファイル操作は、制限されます。 例を以下に示します。(Apache httpd.conf の例)
<Directory /docroot>
php_admin_value open_basedir /docroot 
</Directory>
このopen_basedirの設定で、 同じscript.phpを実行した場合、以下のような結果となります。
Warning: open_basedir restriction in effect. File is in wrong directory in 
/docroot/script.php on line 2

個々の関数を無効にすることも可能です。ただし、disable_functionsディレクティブは php.iniファイルにおいてのみ有効だということに気をつけて下さい。つまり、 httpd.confによるバーチャルホスト毎、ディレクトリ毎の指定は出来ません。 以下の設定をphp.iniファイルに追加してみましょう。
disable_functions readfile,system
この場合、次のような出力となります。
Warning: readfile() has been disabled for security reasons in 
/docroot/script.php on line 2

セーフモードにより制限を受けるか無効となる関数

safe-modeにより制限される 関数のリストを示します。ただし、まだ、不完全で、不正確である可能性 があります。

表 22-1セーフモードで制限される関数

関数制限
dbmopen()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
dbase_open()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
filepro()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
filepro_rowcount()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
filepro_retrieve()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
ifx_*()sql_safe_mode restrictions, (!= safe-mode)
ingres_*()sql_safe_mode restrictions, (!= safe-mode)
mysql_*()sql_safe_mode restrictions, (!= safe-mode)
pg_loimport()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
posix_mkfifo()処理を行うディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
putenv() iniディレクティブのsafe_mode_protected_env_vars および safe_mode_allowed_env_varsに依存します。 putenv()のドキュメントも参照下さい。
move_uploaded_file()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
chdir()処理を行うディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
dl()この関数は、safe-modeでは無効となります。
backtick演算子 この関数は、safe-modeでは無効となります。
shell_exec() (backticksに等価な機能)この関数は、safe-modeでは無効となります。
exec() safe_mode_exec_dir の中でのみ実行可能です。実行上の理由により、現在、実行パスに ..を含めることは許可されていません。
system() safe_mode_exec_dir の中でのみ実行可能です。実行上の理由により、現在、実行パスに ..を含めることは許可されていません。
passthru() safe_mode_exec_dir の中でのみ実行可能です。実行上の理由により、現在、実行パスに ..を含めることは許可されていません。
popen() safe_mode_exec_dir の中でのみ実行可能です。実行上の理由により、現在、実行パスに ..を含めることは許可されていません。
mkdir()処理を行うディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
rmdir()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
rename() 処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。 処理を行うディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
unlink()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。 処理を行うディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
copy()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。 処理を行うディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。 ( source および targetにおいて)
chgrp()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
chown()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
chmod() 処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。 加えて、SUID, SGID, stickyビットを設定できません。
touch()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。 処理を行うディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。
symlink()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。 処理を行うディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。 (注意: ターゲットのみが 確認されます)
link()処理を行うファイル/ディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。 処理を行うディレクトリが実行するスクリプトと同じUIDを有しているかどうかを確認します。 (注意: ターゲットのみが 確認されます)
getallheaders() セーフモードでは、'authorization'で始まるヘッダ(大文字小文字は 区別されません)は返されません。 警告: これは、AOLサーバにおける getallheaders()の実装では正常に動作しません!
php4/main/fopen_wrappers.cを使用する全ての関数 ??