PHP入門 | form送信の基本 | セキュリティ対策の第一歩(XSS防御)
フォームを送信してサーバーで処理するということは、「サーバーサイドプログラミング」の第一歩を踏み出したあなたが、次に必ず行うべきことがあるということだ。それは何だろうか。それは「今作ったプログラムの穴をふさぐこと」である。
サーバーにプログラムを提供するということは、不特定多数の人がそのサーバーにアクセスし、そのプログラムが実行されるということである。つまり、サーバーにアクセスするすべての人に対して「そのプログラムが安全に動作する」ことを保証する義務が発生する。もしそのプログラムによって利用者に何らかの被害が発生すれば、その責任は作成した開発者にある。
もちろん、最初から「すべてのセキュリティ対策を立てろ」という意味ではない。しかし、少なくとも最低限の基本的な安全対策については、プログラムを作り始めたら最初に学ぶべきである。
ところで、今作ったサンプルプログラムには大きな「穴」が空いている。その穴を確認してみよう。ブラウザで前のページにアクセスし、次のように書いて送信してみる。
<script>alert("これが穴です!");</script>
送信すると画面にアラートウィンドウが表示される。最近のブラウザではこれを自動的に防ぎ、警告メッセージが表示される場合もある。入力フィールドに書いたJavaScriptスクリプトが、ページを読み込むときに実行されるため、このような現象が起きる。なぜこれが「穴」なのか。それは「どこの誰か分からない人がここにJavaScriptスクリプトを書き、ページを表示したときにそれを実行させられる」からである。
例えば、このような掲示板プログラムを作ったとしよう。すると、そこにアクセスした人が今と同じようにJavaScriptスクリプトをこっそり投稿する。次にこの掲示板にアクセスしたすべての人に表示されるとき、そのスクリプトが実行される。例えば、そのスクリプトに「ブラウザに保存されているCookie情報を取得して別のサイトへ送る」といった処理が書かれていたらどうなるだろうか。アクセスした人のCookie情報が見知らぬ誰かに盗まれる可能性がある。
いわゆるスプーフィングという犯罪は、このようにして発生する。このスクリプトを利用した方法は「クロスサイトスクリプティング(XSS)」と呼ばれ、サイト攻撃の基本中の基本として広く知られている。
では、この空いた「穴」をふさいでみよう。最初に行うべきセキュリティ対策は、実は意外に簡単である。テキストを画面に表示するecho文のスクリプトを、次のように書き直すだけでよい。
<?php
echo htmlspecialchars($result);
?>
このhtmlspecialcharsという関数は、括弧内に書かれた値、つまり引数をチェックし、HTMLタグをすべてエスケープ文字に変換したものを返す。つまり、このように値を書き出すことで、<script>タグなどをすべて無効化し、動作しないようにできる。
フォームを使う場合には、セキュリティ対策に関する鉄則がある。それは「ユーザーから送られてきたデータを絶対にそのまま画面へ出力しない」ということだ。そこにどのような内容が書かれているか分からないため、必ず「表示しても問題ない」形に処理してから出力することが、フォーム利用の基本である。
<?php
$str = $_POST['text1'];
if ($str != null){
$result = "あなたは'{$str}'と書きました。";
} else {
$result = "何も書かれていません。";
}
?>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>sample page</title>
</head>
<body>
<h1>Hello PHP!</h1>
<div><?php
echo htmlspecialchars($result);
?></div>
<form method="post" action="./index.php">
<input type="text" name="text1">
<input type="submit">
</form>
</body>
</html>