T

変なCSRF対策

au端末のみアクセス可能なサイトでクロスサイトリクエストフォージェリー対策が必要になったのだが、ワンタイムトークンとかのよくある手段だとおもしろくないので、何かないかと考えてみた。

auの端末からのリクエストには、端末の契約情報に紐づいた一意のID(サブスクライバID)がリクエストヘッダとして送信される。そこで、こんなのを作ってみた。

(1)リモートアドレスでauのデートウェイからのリクエスト以外は弾く
(2)POSTリクエストを受け付けるURIはサブスクライバIDで異なる

まあ(1)はよくあることなのでいいとして、(2)はこんな感じになっている。公開するURLは「http://example.com/form」とかいう形式になっている。au端末からそのURLへのリクエストがあると、サーバ側で「https://example.com/xxxxxxxxxx/」にリダイレクトする。この「xxxxxxxxxx」はサブスクライバIDとサーバ側に保持している特定のsaltとなる文字列(例えば創世記の全文)から生成されたハッシュ値になっている。リクエストしてきた端末のサブスクライバIDから生成したハッシュ値とURIのハッシュ値が一致すればリクエストを通して、そうでなければ弾く。リダイレクト処理が入るので「http://example.com/form」へのPOSTリクエストはリクエストボディーの内容が消えたGETのリクエストになってしまうから、もし第三者がこのURLに対してCSRFを仕掛けてきても無効化される。ハッシュ値付きの正しいURLにPOSTリクエストを投げるようにしたくても、端末が送信するサブスクライバIDとsalt値とハッシュ値の生成ルールが分からなければ犠牲者の端末専用のURLが推測できないため攻撃用のフォームを作ることができない。

あとは.htaccessなどで存在しないディレクトリへのアクセスをリライトしてしまえばおしまい。

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

とかいう感じ。いやっほう。

あんまり見たことないやり方なので破り方があるかどうかちゃんと検証できてない気がするけど、思いつかないので実戦投入した。

Posted by on 12月 29, 2009 in Apache, PHP, Security

コメントを残す