「ソースを見る」で見た hidden の値と実際に POST される値が違う

調査依頼。CSRF 対策のために次の機能を入れた。

  1. 更新機能の前の機能でランダム値 (トークン) を払い出す。
  2. トークンをセッションに保存。hidden にも埋め込む。
  3. 更新機能では、セッションに入ったトークンと hidden で送られた値を比較し、同じなら更新処理を実行する。

ところが、この機能が Firefox ではうまく動かない。調べてみると Firefox の場合、「ソースを見る」で HTML のソースに書かれたフォームの hidden の値と、実際に POST したときに送られる値が違っている。
LiveHttpHeaders を使ってすぐわかったのは、トークンを払い出す機能を 2 回 GET していること。IENetscape では 1 回しか GET していない。これは現象ともあっている。すなわち、1 回目のアクセスでトークン 1 を、2 回目のアクセスでトークン 2 を得、
「ソースを見る」で見たときはトークン 2 が見えていてサーバ側で保存しているトークンと一致するが、実際に送信されるのがトークン 1 になるのでエラーになる。

あとは、なぜ 2 回 GET が飛ぶかを特定すること。最初から JavaScript が怪しいと思っていたので、JavaScript を Off にしてみると確かに 1 回しか飛ばなくなる。Firebug で調べてみたら、script の中に HTML 文書がまるごと入っている。いろいろリンクされている JavaScript ファイルを調べていたが、ようやく発見した原因は次の script タグだった。

<script language="javascript" src=""></script>

つまり、src="" となっていると、相対パスで自分自身を指していると解釈し、自分自身を再度リクエストするらしい。

この現象を使うとなんか変なモノが作れそうな予感。