とりあえずは実例で見てみましょう。
http://yuubiseiharukana.creativeroot.jp/php2/php2-3-1.php
<html> <head> </head> <body> <form method="GET" action=" <?php print(htmlspecialchars($_SERVER['SCRIPT_NAME'])); ?> "> <input type="text" name="data"><br /> <input type="submit" value="送信"> </form> <hr> <?php if($_GET['data']){ $x=htmlspecialchars($_GET['data']); print($x); } ?> </body> </html> |
ただ単に送られてきたフォームを表示するという内容です。
フォームがGETなので、
http://yuubiseiharukana.creativeroot.jp/php2/php2-3-1.php?data=あいうえお
と入力すればいきなり結果画面を表示できます。
さて、上のURLへのリンク、これがクロスサイトリクエストフォージェリそのものです。
これは単に表示するだけのプログラムだから特に問題が無かっただけであって、フォームの内容によっては大変なことになります。
http://yuubiseiharukana.creativeroot.jp/php2/php2-3-2.php
<html> <head> </head> <body> <form method="GET" action="<?php print(htmlspecialchars($_SERVER['SCRIPT_NAME'])); ?>"> <select name="to"> <option value="webmaster@xxx.jp">管理者 <option value="userA@xxx.jp">利用者A <option value="userB@xxx.jp">利用者B <option value="userC@xxx.jp">利用者C </select> メールアドレス:<input type="text" name="from"><br /> 本文:<input type="text" name="data"><br /> <input type="submit" value="送信"> </form> </body> </html> |
時々見かける、送信先を選択できるタイプのメールフォームです。
何も考えずにこれを実装していた場合、
http://yuubiseiharukana.creativeroot.jp/php2/php2-3-2.php?from=匿名&data=メールボム&to=aaa@yyy.jp,bbb@zzz.jp,ccc@vvv.jp
というリンクを踏ませるだけでメールを送信できてしまいます。
メソッドがGETのせいだから問題なのだ、POSTならURLを作れないから問題ない、かと思えばそういうこともありません。
http://yuubiseiharukana.creativeroot.jp/php2/php2-3-3.html
<form action="php2.php" method="POST"> <input type="hidden" name="from" value="匿名"> <input type="hidden" name="data" value="メールボム"> <input type="hidden" name="to" value="aaa@yyy.jp,bbb@zzz.jp,ccc@vvv.jp"> </form> <script>document.forms[0].submit();</script> |
こんなフォームを作って適当な場所にアップロードしてしまえば、このリンクを踏んだ時点でメールが送信されてしまいます。
むしろ見た目普通のhtmlなのでより悪質になったというべきでしょう。
あまつさえこのフォームをwhile(1)で繰り返したりしてしまえば、本物のメールボムの完成です。
対処法はいくつかありますが、最初にすべきなのはリクエスト元URLの限定です。
最初のphp1.php以外からのリクエストは受け付けないようにしてしまえば、少なくともリンクを踏ませるだけの攻撃に簡単に引っかかることはありません。
また、selectやcheckboxなどのフォームでは、本来ありえないはずの入力もチェックする必要があります。
もっと言うと、フォームで直接メールアドレスを扱うべきではありません。
フォーム側からは適当なパラメータを渡し、プログラム側で正しいメールアドレスに変換を行うなどの処理を行いましょう。
さて今回のはまだまだ本物のCSRFとは言いがたいので、次回は認証サイト内にも潜り込める、CSRFの本格的利用例でも。