PHP は、ファイルおよびディレクトリ毎に権限を設定する多くのサーバシ ステム上に組み込まれたセキュリティを提供します。これにより、ファイ ルシステム内のファイルを読み込み可能に制御することが可能になります。 全てのファイルは世界中から読み込み可能であり、このファイルシステム にアクセスした全てのユーザから読み込まれても安全であることを確認す る必要があります。
PHPは、ファイルシステムにユーザレベルのアクセスを許可するように設 計されているため、PHPスクリプトから/etc/password のようなシステム ファイルを読み込み可能としたり、イーサネット接続を修正したり、巨大 なプリンタジョブを出力したりすることができます。これから明らかにわ かることですが、読み書きするファイルを適切に設定する必要があります。
各自のホームディレクトリにあるファイルを削除する次のスクリプトを見 てみましょう。これは、ファイル管理用にWebインターフェースを使用す る場合に通常生じるような設定を仮定しています。この場合、Apacheユー ザはそのユーザのホームディレクトリにあるファイルを削除可能です。
例1 甘い変数の確認から生じるリスク
<?php
// ユーザのホームディレクトリからファイルを削除する
$username = $_POST['user_submitted_name'];
$userfile = $_POST['user_submitted_filename'];
$homedir = "/home/$username";
unlink("$homedir/$userfile");
echo "ファイルは削除されました!";
?>
例2 ... ファイルシステムへの攻撃
<?php
// 外部からPHPユーザがアクセス可能なハードドライブを削除します。PHPが
// ルートのアクセス権限を有している場合、
$username = $_POST['user_submitted_name']; // "../etc"
$userfile = $_POST['user_submitted_filename']; // "passwd"
$homedir = "/home/$username"; // "/home/../etc"
unlink("$homedir/$userfile"); // "/home/../etc/passwd"
echo "ファイルは削除されました!";
?>
例3 より安全なファイル名の確認
<?php
// PHPユーザがアクセス可能なハードドライブからファイルを削除する。
$username = $_SERVER['REMOTE_USER']; // 認証機構を使用する
$userfile = basename($_POST['user_submitted_filename']);
$homedir = "/home/$username";
$filepath = "$homedir/$userfile";
if (file_exists($filepath) && unlink($filepath)) {
$logstring = "$filepath を削除しました\n";
} else {
$logstring = "$filepath の削除に失敗しました\n";
}
$fp = fopen("/home/logging/filedelete.log", "a");
fwrite($fp, $logstring);
fclose($fp);
echo htmlentities($logstring, ENT_QUOTES);
?>
例4 より安全なファイル名の確認
<?php
$username = $_SERVER['REMOTE_USER']; // 認証機構を使用する
$userfile = $_POST['user_submitted_filename'];
$homedir = "/home/$username";
$filepath = "$homedir/$userfile";
if (!ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD', $userfile)) {
die("Bad username/filename");
}
//etc...
?>
オペレーティングシステムにより、注意するべきファイルは大きく変化し ます。これらには、デバイスエントリ(/dev/ または COM1)、設定ファイ ル(/etc/ ファイルおよび .ini ファイル)、よく知られたファイル保存領 域 (/home/、 My Documents)等が含まれます。このため、明示的に許可す るもの以外の全てを禁止する方針とする方が通常はより簡単です。