CSRF(Cross Site Request Forgeries)ってリクエスト汚染のことかと思ったらちょっと違うみたいですね。
CSRF問題の概要
例えば、下図のようなServer-A上で動くSNS的サイトがあったとして、会員はログインしてサイトの書き込みページを経由して、記事を書き込んだりできるとします。
- 図1
CSRFの問題があると、下図のようなまったく関係の無いServer-B上からのリクエストを受け付けてしまう、というってことらしい。
でも、これだけでは明らかにおかしいわけで、そのまま書き込めるのなら認証が不十分であったりセッションハイジャックの問題になります。
CSRFは正規のユーザーに成りすましたリクエストを発行することで書き込みなどの悪意ある処理をさせるようです。
(書き込みならまだかわいいものですけど、オンラインバンクなら振込み完了画面へ不正なリクエストを投げるとかになるのでしょう)
で、どうやって正規のユーザーのリクエストを発行するかというと、会員系サイトの良くあるログインパターンでは、入力したIDとパスワードに対し「次回から入力を省略する」なんてチェックボックスがあったりします。
ここにチェックを入れるとセッション情報Cookieに保存され、次回以降はそのセッション情報を持って自動的にログインなんてするわけです。
なので、CSRF問題の前提になるのはユーザーが正規の手続きを踏んでログインした状態である、ということが前提になるみたいです。
つまり・・・
上図のように、ログインした状態のユーザーに対して、どこかで悪意あるサイトへ誘導させ(操作1)、そこサイトを経由して不正なリクエストを元のサイトへ送りつける(操作2)ということをやるみたいです。
上図の場合では、SNSサイト内で「釣り」をして不正なサイトへ誘導(操作1)、不正なサイト上ではページがJavaScriptで自動ロードされ(操作2)、元のSNSサイトへリクエストが飛ぶということをする。
不正なサイト上で、もう一度クリックさせてもいいのでしょうけど、そうすると「なんか怪しい」ということになりますから、ページを読み込んだと同時にJavaScriptで不正リクエストの発行と、まったく関係の無い別サイトへリダイレクトしてしまう、なんてことで隠蔽してしまうことが多いらしい。
これは、そのサイト内で踏ませなくてもSPAMでばら撒いたメール本文に不正なURLを書いておき、受け取ったユーザーがそのサイトの利用者でかつ、そのサイトにログインしている状態であれば発動してしまいます。
こういうことはセッション情報を抜きにすると結構簡単なエラーチェックだけをしているページでは、そのページで必要なリクエストがそろっていれば簡単に抜けてしまう場合があったりします。
例えば、書き込みページから
1. 会員ID
2. タイトル
3. 記事内容
の3つの情報を書き込み完了ページに送っているとすれば、書き込み完了ページでは、
・ 全てのデータがそろっているか
・ 各データ長が範囲内であるか(タイトルは100Byte以内とか)
・ 各データのフォーマットが正しいか(会員IDは数値のみかとか)
というようなチェックをしますが、それらが正しい情報であればどのページからも受け付けてしまう仕様になっているということはあったりします。
まとめると、下図のように正規の経路(Request1: 書き込みページ→書き込み完了ページ)ではなく、別のサイトも含め他のページからリクエストを発行できてしまう(Request2)脆弱性がある、ってことがCSRFの問題。
CSRFの対策
詳細は最後の参考ページに任せるとして、対策の一つとしては一連の処理にトークン(token)を使うやり方があるみたいです。
トークンは、ワンタイムパスワードのように使い、そのトークンが正しければ処理を受付け、トークンが不正であれば受け付けない、ということで別のサイトやページからのリクエストを遮断するのに用いることができます。
例えば書き込みページでトークンを生成し、書き込み完了ページではそのトークンをチェックして正規のユーザーや処理であるかをチェックします。
※ セッション情報とは全く別のものを使う。じゃないとセッション自体は活きている状態から始まるので意味がない。
ページの経路情報だけ正しければいいんだ、ということで前のページの情報(例えばプログラム名とか)を送りつけてチェックするというのも、そのデータを含めてリクエストを作ってしまえばまったく意味がなくなってしまいますし、リファラーのチェックも簡単に偽造できるということから意味を成さないようですね。
あと、CAPTCHA(ゆがんだ画像から数字とか文字を入力させる例のあれ)を使うのも良いみたいですが、これはトークンをユーザー自身で作るようなもので、手間がかかるのであまりお勧めとはいい難いですよね。
(ブログのコメント書くときはよくあったりしますけど)自分自身が書き込みするのにいちいちCAPTCHAの情報を入力するような面倒なサイトはあまり使いたいとは思いません。
どちらかというと、毎回ログインIDとパスワードを求められる方がいいかも。
あれ、でもCSRF問題があるサイト上では、ログイン時のセッション情報をCookieに持たせる云々の話は関係なく、ログインさえしていたら、そのサイト内で釣られたら終るような・・・?
SPAMメールでばら撒かれた場合、そのサイトにログインしていない状態であれば防ぐことは可能そうだけど・・・。
- 参考サイト
PHP と Web アプリケーションのセキュリティについてのメモ
[PR]
[PR]
関連記事
ものすごい数のアタックを受けているようなのでその際のユーザー名を晒す
mod_actionsを使ってドキュメントや画像、Flashファイルを保護する
XSS(クロスサイトスクリプティング)対策に便利なFireFoxアドオンXSS Me
セキュリティ診断ツール「Nikto」を使ってサイトをチェックしよう




