Webアプリケーションにおける脆弱性の一つ。クロスサイトリクエストフォージェリ。
ある悪意ある仕掛けの施されたサイトのWebページを閲覧したとき、閲覧者の予期せぬ別サイトのスクリプト等が実行されてしまう問題。
ユーザがこの攻撃から身を守るのはほぼ不可能であるが、サービス提供者はこの攻撃を回避するよう、CGIプログラムを作成することができる。よって、こういったサービス(mixiなど)を提供する際には、この攻撃を受けないよう、対策を取るべきだと考えられる。
mixiのように、ログインを前提としたサービスであれば、セッション管理用に乱数が使われることが多いが、これを上手に活用することで、ほぼ、CSRFを防ぐことが可能である。
以下は、サービス提供側の対策方法を述べる。
サービスは、ログインした際に乱数等で数列や文字列を作り、それをセッションIDとしてCookieで持ち回して使う。
乱数数列だけでもかなり攻撃に強くなるが、更にハッシュを併用すれば、乱数を使っていることさえ分かりにくくなる。
IDは乱数でなくても良い(例えばkey + user ID + yyyyMMddhhmmssのような文字列のハッシュなど)が、外部から容易に推察可能なものは避けねばならない。
この数列や文字列はできるだけ桁数を多くすると、偶然のなりすましを防ぐことができる。
このセッションIDは、発行以降ログアウトするか一定の寿命を迎えるまで、サービスを利用するパスワードとなる。
なお、このセッションIDは、必ずログインしてから作成し発行すること。さもないと、セッション固定攻撃の対象となる。
「確認画面」を作れば防げる、などとする対策案を提示する者がいるが、無駄である。攻撃者は、その次の実行画面に直接攻撃を加えるからである。
そこで、機能は次の3画面で構成することにする。
述べる迄もないが、CGIが動くのは、1と2の間、2と3の間である。
通常の攻撃スタイルは、いわゆる1パスであり、あるタイミングでCGIに直接データを送ることで実現する。
従って上述の例であれば、攻撃者は2→3の段階のCGIを、ターゲットとするだろう。セキュリティ強化は、この段階を重点的に行なうこととする。
そこで、最後の2→3の段階で、その投稿が本当に本人からの要求であるかを確認する。
具体的には、画面2ではセッションIDをinput要素にhiddenで含め、処理系はこのセッションIDと、Cookieから与えられるセッションIDが一致するかを確認する。異なる場合は、投稿を受け付けないようにする。
この方法だけで、CSRFはかなり防げる。
但し、1→2を実行してセッションIDを得たあと、更に2→3を実行するような、2パスの攻撃は避けられない。
こういった悪質極まるセッションハイジャックには対応するのは、かなり難しいと思われる。それと同時に、これを全自動で行なう処理を作るのもまた、かなり難しいと思われる。
そこで完全な対応ではないが、攻撃側実装を困難にするため、少なくとも画面1にはセッションIDは含めないようにする。
セッションIDを得るためには少なくとも画面2を得ねばならないとすると、画面1→2の間のCGIで、状況に応じた何らかの対応をすることも可能となるだろう。