PHP - WEB - 15. ドキュメントルートの指定
引き続きWebアプリケーションのセキュリティについて学習していきましょう。ここではWebサーバのドキュメントルートやコンテンツの公開範囲について考えます。
ドキュメントルート
ドキュメントルートとは、Webサーバ上で公開する基点となるディレクトリのことです。ドキュメントルートに指定したディレクトリの中にあるディレクトリやファイルは、Webブラウザから直接アクセスすることができるようになっています。そのためドキュメントルート下に、機密情報を扱うような重要なファイルを配置してしまうと情報漏えいのリスクが生まれます。
PHPプログラムの開発(ドキュメントルートの指定)
ここではさきほどのチャットプログラム( chat.php
)を例にドキュメントルートの指定について考えてみましょう。ビルトインWebサーバを起動している状態で、以下のURLにアクセスするとチャット画面が表示されます。
http://localhost:8000/chat.php
このとき chat.php
と同じディレクトリ上に chat.txt
ファイルを配置しているので、アドレスバーから以下のようにURLを入力すると直接 chat.txt
ファイルにアクセスできてしまいます。
http://localhost:8000/chat.txt
今回のようなチャットのメッセージが表示されるだけであれば問題ないかもしれませんが、個人情報を扱うような重要なファイルにアクセスされてしまうと被害は大きくなってしまいます。
このよう問題を防ぐために、データを扱うファイルはドキュメントルート下に配置しないようにします。ここでは以下に示すディレクトリ構成に変更します。またビルトインWebサーバの起動時にドキュメントルートとして webapp
ディレクトリを指定するようにします。
- カレントディレクトリ
- webapp
- chat.php
- data
- chat.txt
新しいディレクトリ構成について確認していきましょう。まずカレントディレクトリ( /Users/your_name/Desktop/code-php
など)に webapp
ディレクトリと data
ディレクトリを作成します。 webapp
ディレクトリにはPHPのプログラム( chat.php
)を配置し、 data
ディレクトリにはデータを扱うファイル( chat.txt
)を配置します。
ディレクトリ構成を変更したことでチャットプログラム( chat.php
)にも一部修正が必要になります。
<?php
$file = "../data/chat.txt";
$messages = file($file, FILE_IGNORE_NEW_LINES);
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$message = (string)filter_input(INPUT_POST, "message");
if ($message !== "") {
$messages[] = $message;
file_put_contents($file, $message . PHP_EOL,
FILE_APPEND | LOCK_EX);
}
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHP Sample</title>
</head>
<body>
<h3>Chat</h3>
<hr>
<form action="chat.php" method="post">
<input type="text" name="message">
<input type="submit" value="send">
</form>
<ul>
<?php for ($i=0; $i < count($messages); $i++) { ?>
<li><?php echo htmlspecialchars($messages[$i]); ?></li>
<?php } ?>
</ul>
</body>
</html>
ここでは先頭部分の chat.txt
ファイルのパスを修正しています。
$file = "../data/chat.txt";
ここでは相対パス指定で data
ディレクトリに配置した chat.txt
を参照できるように修正しています。先頭の ../
の部分は親ディレクトリを意味しており、 chat.php
ファイルの所属する webapp
ディレクトリから1つ上位のディレクトリに上がり、そこから data
ディレクトリ下にある chat.txt
ファイルを指定しています。このようにPHPのプログラムはドキュメントルートの外に配置しているファイルにもアクセス可能です。
プログラムを修正したら、一度ビルトインWebサーバを停止します。それからビルトインWebサーバを起動します。このとき -t
オプション(ドキュメントルート)に webapp
ディレクトリを指定します。
$ php -S localhost:8000 -t webapp
上記のように起動することで、ビルトインWebサーバのドキュメントルートを webapp
ディレクトリに変更できます。
それではWebブラウザを開いてアドレスバーからチャット画面( chat.php
)にアクセスしてみましょう。
http://localhost:8000/chat.php
表示されたチャット画面では以前と同じようにメッセージを投稿できます。
送信ボタンをクリックすると次のように表示されます。
またテキストエディタで chat.txt
ファイルを確認してみると正しくメッセージを追記できているのがわかります。
Hello World!
<script>alert('Script Injection!')</script>
Change DocRoot
それから以前のようにアドレスバーから直接 chat.txt
ファイルにもアクセスしてみましょう。
http://localhost:8000/chat.txt
そうすると以前のような chat.txt
ファイルへのアクセスは失敗し、 Not Found
という表示されたエラー画面を確認できるでしょう。
このようにデータを扱うファイルの配置場所を工夫することで、Webブラウザからの直接的なアクセスを禁止できます。
まとめ
- ドキュメントルート以下に配置したファイルは公開されてしまう
- 重要なファイルはドキュメントルート以下に配置してはいけない
- PHPプログラムからはサーバ上の非公開ディレクトリにもアクセスできる