フォームの2重送信の防止…

10月 21, 2007 Security
(Last Updated On: 2013年12月3日)

ちょっと気になったので…
記事はコラム形式だったので書いていないだけだと思いますが2つ問題があります。

1. 識別可能なフォームの数に限りがある
セッション変数を利用しているため変数名でフォームを識別する必要があり、ユーザが複数のフォームを利用した場合、正しく動作しない。この制限をなくす事もできますが、その場合セッション変数が大きくなりすぎた状態に対処するようにしないとならくなります。(ガーベッジコレクションの実装が必要)

2. レースコンディションによる2重投稿の可能性がある

コードを見て分かる通り

if (isset($_POST['submit_button'], $_SESSION['ticket'], $_POST['ticket']) && $_SESSION['ticket'] === $_POST['ticket']) {
    unset($_SESSION['ticket']);

セッション変数の状態チェックと状態の変更がアトミックに行えないため、稀なケースとは言えますが、レースコンディションにより2重送信の可能性があります。

この様な変数の状態の確認と変更はアトミックな処理が必要になります。

Webサーバが一つならセマフォを使えますが、複数のWebサーバを利用する場合、トランザクションをサポートしたDBサーバを利用します。(APサーバ間でトランザクション、と言う方法もありますがDBサーバを利用した方がスケーラブルです)

私のPHPの本、セキュリティの本でもこの方法を2重送信・CSRF対策として紹介しています。

投稿者: yohgaki