ユーザからの入力
PHPを使ってWebアプリを作成する上で、HTMLのフォーム値や、URLパラメータの値を取得し、何らかの処理を行うことは避けては通れないところでしょう。また、この何らかの値を取得し、処理を行うというところがWebアプリの攻撃窓口でもある訳です。
URLパラメータ値の取得
それでは、早速、URL(GET)パラメータの値を取得する簡単な入力例です。
get_example.php
<?php
// URLパラメータ値を表示
echo $_GET['value'];
Webブラウザから、このプログラム(get_example.php)に適当な値を指定して攻撃...おっと、アクセスしてみてください。例えば、次のようにアクセスします。
http://サーバのアドレス/プログラムが保存されているディレクトリ/get_example.php?value=somevalue
パラメータvalueにsomevalueを指定してアクセスしています。
get_example.phpの実行結果
単に値を取得し、出力するだけなら、プログラムは1行で済んでしまいますね。『$_GET[なんとか]』は、PHPであらかじめ定義されている変数です。$_GETには、URLパラメータ名とその値が自動的に代入されます。
変数名の後に『[』と『]』で文字列が囲まれていますが、これは配列の形式です。(配列については後ほどゆっくりと説明したいと思います。)この『[]』で囲まれた部分に取得したいパラメータ名(例ではvalue)を記述します。
とても簡単ですね。それでは、2つのパラメータと値の組を取得してみましょう。
get_example2.php
<?php
// URLパラメータ値を表示
echo $_GET['value1'];
echo '<hr />';
echo $_GET['value2'];
複数のパラメータと値の組を指定するには、&で繋ぎます。例えば、次のようにアクセスします。
http://サーバのアドレス/プログラムが保存されているディレクトリ/get_example2.php?value1=val1&value2=val2
get_example2.phpの実行結果
HTMLフォームからの値の取得
以下は、HTMLフォーム(POST)の値を取得する簡単な例です。
post_example.php
<?php
echo $_POST['value'];
?>
<form action="" method="post">
<input type="text" name="value" />
<input type="submit" name="commit" />
</form>
post_example.phpの実行結果(『peabox.com』と入力して送信)
HTMLフォームのaction属性には何も指定していませんが、この場合、プログラムファイル自体(つまり、post_example.php)をもう一度読み込んで、送信された値を出力するようになっています。『$_POST[なんとか]』は、定義済みの変数で、$_GETと同様、$_POSTには送信されたパラメータ名(フォームのname属性)とその値が自動的に代入されます。
複数の値を取得してみましょう。
post_example2.php
<?php
echo 'text1: ' . $_POST['text1'];
echo '<hr />';
echo 'text2: ' . $_POST['text2'];
echo '<hr />';
echo 'radio: ' . $_POST['radio'];
echo '<hr />';
?>
<form action="" method="post">
<div>text1:<input type="text" name="text1" /></div>
<div>text2:<input type="text" name="text2" /></div>
<div>
<input type="radio" name="radio" value="radio1" />radio1
<input type="radio" name="radio" value="radio2" />radio2
</div>
<input type="submit" name="commit" />
</form>
post_example2.phpの実行結果
出力サニタイズ
上記4つの例では、入力された値をそのまま出力しているのですが、このコードのままでは、攻撃窓口になってしまいます。具体的な攻撃方法は、ここでは触れませんが、ごく簡単なJavaScriptコードなどを入力、送信(スクリプトインサーションやクロスサイトスクリプティング)でそれは可能でしょう。
では、どうすればそのような攻撃に対処できるのでしょうか?問題なのは、悪意あるプログラムコードが入力され、実行されてしまうことにあります。つまり、入力されたプログラムを実行させないような処理が必要になる訳です(こういった処理は、サニタイズ処理とか、エスケープ処理と呼ばれます)。
PHPには、そのようなサニタイズ用処理の関数も用意されています。以下はそのうちの1つ、『htmlspecialchars()』を使った例です。
post_example3.php
<?php
echo 'text1: ' . htmlspecialchars($_POST['text1'], ENT_QUOTES);
echo '<hr />';
echo 'text2: ' . htmlspecialchars($_POST['text2'], ENT_QUOTES);
echo '<hr />';
echo 'radio: ' . htmlspecialchars($_POST['radio'], ENT_QUOTES);
echo '<hr />';
?>
<form action="" method="post">
<div>text1:<input type="text" name="text1" /></div>
<div>text2:<input type="text" name="text2" /></div>
<div>
<input type="radio" name="radio" value="radio1" />radio1
<input type="radio" name="radio" value="radio2" />radio2
</div>
<input type="submit" name="commit" />
</form>
htmlspecialchars()関数は、HTMLの特殊文字(<や&など)をエンティティ文字に変換します。最初の引数に変換したい文字列を指定します。2番目の引数『ENT_QUOTES』はクォート(『'』)も変換対象に含める場合に指定します。
タグをエンティティ文字に変換することができれば、<script>タグとして受け付けることができないということです。ユーザからの入力を受け付けるプログラムでは、必ずサニタイズ処理を行うようにしてください。