[PHP-users 35626] 登録フォームの作成でアドバイスを頂きたいのですが

yk_mailing @ mail.goo.ne.jp yk_mailing @ mail.goo.ne.jp
2011年 10月 29日 (土) 20:48:08 JST


アカウント登録のフォーム作成時のセキュリティについてなのですが、

アカウント登録用スクリプト : reg.php
アカウント登録用テンプレート : reg.tpl
記述内容チェック用スクリプト : check.php
とします。
reg.phpにname、password、password確認、emailの4つのテキストエリアで考えた場合に自分は、

★まずreg.php、check.phpでセッションをスタート、
session_regenerate_id(TRUE);を加え、
md5化したワンタイムチケットをreg.phpセッションとreg.tplのhiddenに埋め込みました。
check.phpで$_SESSION['ticket'] === $_POST['ticket']ならOK、
セッションのチケットを削除。

他にもreg.phpで、$_SERVER['HTTP_USER_AGENT']の値をセッションに格納しcheck.phpのものと確認、
加えて$_SERVER['HTTP_REFERER']がreg.phpと照合するかを確認しました。


★次にcheck.phpにて4つの$_POST値を全て(string)に型変換し、Validateを行いました。
自分で正規表現等でやっても良かったのですが、Zend_Validateを使い、

まずnameとpasswordでZend_Validate_Alnum()にて英数字かを確認、
次にZend_Validate_StringLength()にて32文字以下かどうかを確認しました。
passwordはsaltを加え、md5()化するため32文字にしました。
reg.tplの<input>も一応maxlength="32"で保険をかけました。
Emailに関してはZend_Validate_EmailAddress()->Zend_Validate_StringLength(10, 66)としました。

Validateエラーがあれば、エラーメッセージをセッションに格納しreg.phpにリダイレクトして表示。


★データベースへの登録はPDOにてprepare()->bindParam()->execute()の流れで登録、
出力はSmarty3にてdefault_modifiers = array('escape:"htmlall"')を設定。
これらによりエスケープは自分で処理する必要はないのかなと思い、個別にaddslashes()やhtmlspecialchars()などはいっさい使用しておりません。

NULLバイト対策も考え、
function sanitize ($arr)
{
if (is_array($arr))
{
return array_map('sanitize', $arr);
}
if (preg_match('/\0/', $arr))
{
die("不正な入力です");
}
return str_replace("\0", "", $arr);
}
$_POST = sanitize($_POST);
としたのですが、ブラウザには普通に%00や\0とかが出力されていて、良く分かりませんでした。
例文など見ても$_GETの状況の事しか書かれていないので、$_GETの時だけの問題なのかな?とも思ったりもしました。


★後は二重投稿を禁止するためにリロード対策(ワンタイムチケット法がその対策になっている?)や、
(登録フォームではなくログインフォームででしょうが)ある一定の回数エラーを出してリダイレクトするようならば不正アクセスとしてセッションにリダイレクト回数を設定し、暫く認証禁止とかかなと思います。


以上、上記のような作りをしてみたのですが、セキュリティ上問題のある部分はありますでしょうか?
自分にはこれ以上あまりやる事が思いつかないのですが、こんな簡単な実装ではダメだろうなと思い質問させていただきました。
ここは危険とか、もっとこういう実装を加えなきゃいけないというようなものがありましたらアドバイス頂きたいと思います。


PHP-users メーリングリストの案内