Twitterのフォロワーさんと話していて、既にありそうだけど、もしかしたら使えるかもしれないフォームのセキュリティを見つけたので書いておきます。
例えば一般的なログインフォームはこんな感じですね?
index.php
<?php
mb_internal_encoding("utf-8");
@session_start();
if (isset($_SESSION['login'])&&$_SESSION['login']=="login") {
echo <<< EOM
ログイン
<form action="./logout.php" method="post">
<input type="submit" value="ログアウト"></input>
</form>
EOM;
}else{
echo <<< EOM
<form action="./login.php" method="post">
<label>ID</label>
<input name="username"></input>
<label>PW</label>
<input name="userid"></input>
<input type="submit" value="ログイン"></input>
</form>
EOM;
}
?>
login.php
<?php
mb_internal_encoding("utf-8");
@session_start();
if(isset($_POST['username'])&&
isset($_POST['userid'])&&
$_POST['username']==="admin"&&
$_POST['userid']==="root"){
$_SESSION['login'] = "login";
}
header('location:./');
?>
これはID(username)にadmin、PW(userid)にrootと入れるとログインできます。
しかしこれだと辞書攻撃などで容易に突破できてしまいます。
そこでlogin.phpをこう変えます。
login.php
<?php
mb_internal_encoding("utf-8");
@session_start();
if(isset($_POST['username'])&&
isset($_POST['userid'])&&
$_POST['username']==="admin"&&
$_POST['userid']==="root"&&
$_POST['pass']==="pass"){
$_SESSION['login'] = "login";
}
header('location:./');
?>
1行追加しただけですが、表のフォームには出ない値passを検査しています。これに入るためにはindex.phpをブラウザを表示した後、検証ツールなどでpass入力用のinputを追加してあげる必要があります。
シンプルですが、そもそもその追加するルールをわからなければいけない事とnameと値が分からなければ辞書攻撃で突破されないフォームが出来ている気がします。例えば追加するinputの数を多くしたり、type="hidden"で見た目を偽装すれば更に強固になっていくのではないでしょうか。
自分の知識だとこの方法は聞いたことがないのですが、既に名前が付いていたり弱点があったりするんでしょうか・・。
偽のログインサイトとか作られたらダメそうだけど