Interop Tokyo 2022出展レポート

クロスサイトリクエストフォージェリ(CSRF)とは?対策は?例を使って分かりやすく解説!

シェア ツイート

こんにちは。

今回は三大脆弱性最後の一つ、クロスサイトリクエストフォージェリ(CSRF)の回です。いよいよ「三大脆弱性シリーズ」も4回目になりました。楽しくなってきましたね、脆弱性の勉強。あータノシイナー。

では早速、といきたいところですが本題に入る前に、まずはCookieの話を。これが頭に入っていなかったもちゃじは理解に苦しんだことをそっと告白しておきます。

情報漏洩ニュースのたびに「うちのサイトは大丈夫かな」と心配されていませんか?

脅威に対する「安心」が手に入れば、心配事はなくなります!

CookieとセッションID

ブラウザを使ってWebサイトを見るとき、実は私たちの見えないところで「Cookie」が活躍しています。Cookieは「ブラウザの情報保存機能」です。例えば、Webサイトに訪れた人が同じ人ということを識別するのにも、使われたりします。

本来、サーバーさんは一期一会の刹那主義なので、同じ人からのリクエストであっても、それを判別することができません。だから、会員サイトにログインしたとしても、次にアクセスしたときにその人がログインした人なのかが分からないんです。一回一回リクエストの記憶がリセットされちゃうから。

Cookieがない世界のやりとり

ブラウザ:会員サイトのページ頂戴
サーバー:どうぞーここからログインしてください
ブラウザ:IDとパスワードを送るので認証してね
サーバー:もちゃじさんですね?認証確認OKです
ブラウザ:ありがとー。じゃあ私のマイページを表示して
サーバー:え?あなた誰?ログインしてないじゃん

このように。

それではいろいろと大変ですよね。そこで、クッキーを使った「セッションID」の登場です。

先ほどの、会員サイトにアクセスしてログインする場合。会員サイトのサーバーさん、セッションIDを作ってログインしたもちゃじとひも付けて保存。会員サイトの画面をブラウザに渡すとき、クッキーとしてセッションIDも一緒に渡します。

ブラウザさんは、送られてきたCookie(セッションID入り )を保存します。ここで、「Cookie」が登場します。こんな感じ。

Cookieがある世界のやりとり

ブラウザ:会員サイトのページ頂戴
サーバー:どうぞーここからログインしてください
ブラウザ:IDとパスワードを送るので認証してね
サーバー:もちゃじさんですね?認証確認OKです。じゃあこのCookie(セッションID:d1A5)をあげます
ブラウザ:ありがとー。じゃあ私のマイページを表示して。あなたからもらったCookieはこれです
サーバー:え?この人誰だっけ?(受け取ったCookieをゴソゴソ……)「セッションID:d1A5」のCookieがある……ああ、さっき認証確認OKだったもちゃじさんか。もちゃじさんの情報ページどうぞー。

Webサイトのサーバーさんとブラウザさんで、それぞれ情報をやりとりして、便利にしてくれてるんですねー。そして、そのやりとりにはCookieの存在が。はーありがたやー。

では、改めてきちんとCookieの話を。
もちゃじのつまずきポイントでもあるので、より詳しく見ていきたいと思います。クロスサイトリクエストフォージェリの理解のため、お付き合いください。

冒頭で「Cookieはブラウザの情報保存機能」といいました。ブラウザにポケットがあるとイメージしてください。情報を入れるポケット。

Webサイト(例えば、会員.web-scan.jp)へのログインが成功したら、会員.web-scan.jpのサーバーから「ログイン成功の証しとひもづいたCookie(セッションID)」をもらいます。それをブラウザのポケットに保存します。

会員.web-scan.jpのサーバーは、他のサーバーと同じく一期一会の刹那主義のため、毎回のリクエストが同じ人なのかを判別できません。

なので、会員.web-scan.jp印の「ログイン成功の証しとひもづいたCookie(セッションID)」を持っているブラウザかどうかで、ログイン状態を判定します。

具体的にいうと、ブラウザは、会員.web-scan.jpのサーバーにアクセスするときには、会員.web-scan.jp印のCookieを全て送ります。会員.web-scan.jpのサーバーは、そのCookieの中に「ログイン成功の証しとひもづいたCookie(セッションID)」があれば、そのブラウザをログイン状態と見なすんです。

CookieとセッションID、めっちゃ助かりますねー。
ところが、その仕組みを悪用するのがクロスサイトリクエストフォージェリ攻撃なんです。

クロスサイトリクエストフォージェリって?

やっと本題に入ります。
クロスサイトリクエストフォージェリ(Cross-Site Request Forgeries )は「CSRF」と略されます(長いので次からCSRFと記載しますね)。訳すと「サイトをまたいだリクエスト偽造」。うんうん、完全に響きが脆弱性。いや、そうなんだけども。三大脆弱性なんだけども。

あれ、でももう一つの三大脆弱性、クロスサイトスクリプティングはXSSと略しますよね。クロスサイト部分は同じなのに。物の本によると、英語のCross Site Scriptingのまま略すと、Cascading Style SheetsのCSSと紛らわしいから(意訳)クロスサイトスクリプティングはXSSとしているらしいです。なるほど。

早速脱線しました。すみません。

罠サイトと標的サイト

さて、CSRF「サイトをまたいだリクエスト偽造」についてですが「サイトをまたいだ」ということで、二つ以上のWebサイトが登場することがにおいますね。そして「リクエストを偽造」。ふむ。

二つ以上のWebサイトの間でリクエスト偽造により被害が出てしまうんだな、と名前から予想がつきますね。予想通り、あるサイトにログイン状態であるとき、罠が仕掛けられた別のサイトを介して本人が意図しない偽のリクエストが送られることで、処理が実行されてしまう脆弱性なんです。

CSRFの被害は、こんな流れです。

二つのWebサイトは、悪い人が作るのを「罠サイト」、もちゃじがいつも使うのを「標的サイト」、これはもちゃじの心に安寧をもたらしてくれる推しのWebサイト「推しサイト」としましょう。

もちゃじは今日も夜の日課、推し周辺のパトロールに余念がありません。まずは推しサイトにログイン。はぁ、癒やされる。他のWebサイトでも情報収集。情報が情報を呼び、もちゃじのブラウザのタブはどんどん増えていきます。もちろん、いつでも推しサイトに戻れるようにキープログイン。

さまざまな推しの情報に癒やされていると、「推しの抱き枕はこちらのスペシャルサイトまで!」と書かれたメールが届きました。推しの抱き枕!ということですかさずリンクをクリック。

しかし、実はこのリンク、推しの抱き枕のスペシャルサイトへのリンクではなく、悪い人が作った罠サイトへのリンクだったのです。このサイトには、CSRFの脆弱性をついた処理が仕掛けられています。

もちゃじは罠サイトにアクセスするのですが、この罠サイトには、推しサイトのコメント投稿ページに「推し批判コメントを投稿するリクエスト」を送信するような処理をブラウザに送ります。ブラウザは、その処理を即座に実行するので、もちゃじは何が起きたのかは、分かりません。

ざっくりいうとこれが、CSRFの脆弱性。

どんな流れで攻撃が起きるのか詳細は、こちらの記事(https://web-scan.jp/article/1794/)の「3.他人になりすまして攻撃、クロスサイトリクエストフォージェリ」をご覧ください。

クロスサイトリクエストフォージェリ脆弱性の原因

あるWebサイトから発行された「セッションを維持するための情報」が、別のサイトを介したリクエストの送信時にも送られてしまうから。

注意が必要なWebサイト

Cookieをつかったセッション管理、Basic認証、SSLクライアント認証を用いているとCSRF攻撃、危ないかもしれないんですって。特に、ネットバンキングやネット証券、買い物やオークションなど、ログイン後に決済処理などを行うWebサイトは要注意! 

そもそもログイン機能を持つWebサイトは、注意した方が良さそうです。

想定される被害

対策が採られていないWebサイトにログインしたまま「罠サイト」に行ってしまうと、「罠サイト」から良からぬリクエストが送られてしまい、イタズラされてしまう。イタズラって何だよ……

ズボラなもちゃじは、いちいちログアウトしないんですよね。ログインしっぱなし。そのWebサイトが何も対策していなかった場合、知らない間に勝手に投稿されちゃったり、買い物されちゃったりするんです。これ、通常の掲示板だったら、投稿前の確認がありますよね。でも、罠サイトのリンクを踏んでしまっている場合、そんなもんありません。勝手に投稿されてしまいます。ECサイトでも同じです。

過去には、CSRFの脆弱性によって掲示板に犯罪予告が投稿されてしまった例もあるようです。罠サイトにアクセスしてしまったがために、悪い人が偽造したリクエストが送信されてしまうという仕組み。

イタズラって言葉が軽い! いじめと同じく軽い!! やってることは犯罪!!!

対策

防ぎましょう。ちゃんと対策ありますから!
Webサイトを作っている側と、Webサイトを利用する一般ユーザー側で分けて見ていきましょう。

Webサイトを作る側の対策

乱暴にいってしまえば、悪いことをたくらむ「罠サイト」や別サイトからのリクエストに応じなければいい話。簡単にいってくれるよなぁっていうため息と、お前が言うなのブーイングが聞こえた気がする。うん、鈍感力でスルー。

根本的対策その1! POSTメソッドでアクセス&hiddenパラメータに秘密情報を挿入

秘密にしておきたい大切な情報はPOSTメソッドでアクセスするようにすること。これ、基本中の基本なんですって 、先輩いわく。

Webアプリケーションでは、サーバーにリクエスト(要求)を送信する方法が2種類あって、それが「GET方式」と「POST方式」。

GET方式

URLの後ろに処理に必要な情報をくっつけて送ること。画面表示など、ページを取得するだけの単純な場合はこちらの方式を使うそうです。

例えばこういうの。
https://mochaji-oshi.web-scan.jp/search?titleId=8

なんか、見たことありますね。「?」とか「&」とか入っているURL。

意味は
「?」:ここからパラメータだよ
「?」以降:パラメータ名=データ 

https://mochaji-oshi.web-scan.jp/search?titleId=8
(訳:タイトルIDが8のページを頂戴)

「GET」は、正々堂々と分かりやすく情報を渡しているのか。
でもこれって、URL上にパラメータが丸見えになっちゃうんじゃ……

POST方式

URLに情報をくっつけずに送る。ログインIDや個人情報、長いテキストや写真など、秘密にしたい情報や大きなデータを送信するためのリクエストを送る場合はこちらの方式を使います。

大事なことは分からないように、ですね。

そして、この「POSTメソッドでアクセス」して「hiddenパラメータに秘密情報を入れる」っていうのがセットの対策なので、次に「hiddenパラメータ」について、説明します。

「hiddenパラメータ」に秘密情報を入れる

「hiddenパラメータ」。「hidden」に「秘密情報」。良いですね。字面だけで厨二病がうずきます。

「hiddenパラメータ」は、Webサイトなどの画面に表示せずに情報を入れておける魔法の箱、とでも思ってください。その箱に「秘密の合言葉」を入れておいて、その「合言葉」が正しいときだけ処理がなされる。うん「合言葉」良いですね、暗号みたい。

例)もちゃじは推しサイト(mochaji-oshi.web-scan.jp)に、レビューを投稿したい。そのときWebサイトの裏側では?

① レビュー投稿の入力画面にmochaji-oshi.web-scan.jpが、今回のレビュー投稿でしか使えない合言葉をこっそり仕込む
② レビュー投稿ボタンをクリックしたら、合言葉も一緒に(こっそり)POSTで送る。このときCookie(ログイン済みのセッションID)も一緒に送信される
③ ログイン済みのセッションIDが送られてきたので、ログイン状態であることを確認。正しい合言葉が一緒に送信されている場合のみ、レビューの投稿は許可される

レビュー投稿処理の中で、ログイン状態だけでなく、合言葉が合っているかチェックすることで、レビュー投稿画面から送信されたリクエストであることが分かる、ということらしい。

そして、POSTのhiddenパラメータでこっそり送っているからといって油断は禁物です。合言葉は毎回変えること。そして人が予測できないような長くて複雑な文字にすること。秘密の情報は誰に見られるか分からないから要注意。

根本的対策その2!処理実行の直前で再度パスワードを求める!

処理を実行する前に、その処理を実行していいかどうかを確認するために、例えばパスワードの入力を求めます。

例)もちゃじは推しサイト(mochaji-oshi.web-scan.jp)に、レビューを投稿したい。そのときWebサイトの裏側では?

① 送信されたCookieにログイン済みのセッションIDがあるので、もちゃじはログイン状態であることを確認
② レビュー投稿の直前に、投稿する内容とパスワード入力画面を用意する
③ その画面でパスワードの入力を促す 
④ パスワードがOKならレビュー投稿を実行

「Cookieでログイン状態は確認できたけど、本人が意図したレビュー投稿かどうか確認してもらいたいし 、念のためにもう一度パスワード教えてね」ということか。あと、投稿と同時にパスワードを送ることが大事なんですって、先輩いわく。

根本的対策その3!このページはどこから来たのかを確認する!

ページがどこから来たのかを確認するには、「Referer」情報を確認します。
「Referer」とは、直前に見ていたページのURL情報のこと。ブラウザからWebサーバーへ送られるリクエストの中に書いてあります。

Refererを見て、正しいリンク元か確認し、正しい場合にのみ処理を実行します。

例)もちゃじは推しサイト(mochaji-oshi.web-scan.jp)に、レビューを投稿したい。そのときWebサイトの裏側では?

① レビュー投稿リクエストを受け取る
② リクエストと一緒に送られてきたCookieにログイン済みのセッションIDが含まれていたので、ログイン済みであることを確認
③ リクエストの中の「Referer」をチェック
④ Refererに「mochaji-oshi.web-scan.jp」とあれば正常、レビューを投稿

注意したいのは、罠サイト(イタズラの処理)が推しサイトの中に作られていたら、もうお手上げ。Refererチェックだけでは防げません。さらに、ブラウザの設定で、Refererを送らないようにもできるみたいなので、この方法は完璧じゃないのか……

と、ここまではWebアプリケーションの仕様をガッツリ変えて防御する対策でした。

もちゃじレベルの皆さん、大丈夫ですか?もちゃじはダメです。頭から湯気出そう。いったん水でも飲みます。

さ、気を取り直して、次はブラウザに依存した対策方法です。

保険的対策その1!モダンブラウザの機能を使った対策~俺だけのCookie

CSRFへの対策は、実はWebサイト側でCookieに属性を設定することで対策することができるようになりました。しかし、CSRFの脆弱性が後を絶たないことから(もちゃじの予想)、ブラウザ側でも対策をしようということになり、現在「送信元のホスト名が違うなら、Cookieは送りません」という設定が多くのモダンブラウザさんのデフォルトの設定になりました。

その属性の名前は「SameSite属性」。これによって、意図しないCookieの送信を防ぐことができます。

ただし、「送信元のホスト名が違うなら、Cookieは送りません」だけだと、これまで「送信元のホスト名が違っても、Cookieを送ってあれこれしてたWebサイト連携」ができなくなってしまいます。そこで、SameSite属性では「Cookie発行後、2分以内だったらクロスサイトの利用OK」ということもできます。

うん、良いですね。俺だけのCookieだけど、2分間だけなら貸し出してやるぜ。ただ、将来的には、なくなるかもしれないんですって、先輩いわく。

保険的対策その2!重要操作を行ったら登録されているメールアドレスに連絡を入れる

ここまでいくつか対策を見てきましたが、それに加えて、メールの自動送信っていうのもあるようです。何か重要な操作がされたときに、登録メールアドレスにその旨を自動送信される。もちゃじも、ユーザーの皆さんも、えっ?何これ?もしかしてなんかまずいことになってるんじゃ……って気づく、というもの。

受け身ではあるんですが、自分で気づくように、という対策ですね。

では次に、ユーザー側ができる対策を紹介します。大丈夫、あと少しで終わります。

一般ユーザー側でする対策

1.不審なページにアクセスしない

いつでもどこでもいわれていることですが、これに尽きます。見た目で不審なWebサイトかどうかを判別するのは難しいとは思いますが。セキュリティソフトがあるので、活用するのも手です。

2.ログアウトする

利用終了後に必ずログアウトすること! ズボラなもちゃじ、これには気を付けようと思いました。ログイン状態が悪用されるのであれば、ログアウトして防ぐ! 簡単ですね。ログアウトするだけですから。自衛です。自分に言い聞かせています。

3.身に覚えのないものは運営に連絡相談

CSRFの被害を自覚するのは難しいです。変な投稿をされてしまっても、周囲の指摘がなければ気づかないこともあります。オンラインバンキングやクレジットカードの不正利用なども、すぐには気づきません。後に請求書や明細などで気づくかも。金銭的な被害に止まらず、何か身に覚えのない投稿などがあった場合にも、すぐにサービスの運営元に連絡を! 相談して対応してもらいましょう。

まとめ

CSRFは、あるWebサイトから発行された「セッションを維持するための情報」が、別のサイトを介したリクエストの送信時にも送られることで意図しない処理が実行されてしまう、 脆弱性またはその攻撃のことでした。

まあでも、CSRFは「POSTメソッドでアクセスして、hiddenパラメータに秘密の合言葉を入れる」など根本的に解決してしまう対策があります。消滅がまことしやかにうわさされているんですが、対策が有効だからなんです。

今回出てきた用語

セッションユーザーがWebサイトにログインしてからログアウトするまでの一連の流れなど(どの範囲をセッションと定義するかによって変わります)
セッションIDセッションの開始時に払い出される識別番号。以後、セッションIDの受け渡しにより、同一のセッションかどうかを識別できるようになる
Basic認証HTTPにあらかじめ用意されているIDとパスワードで認証する仕組み
SSLクライアント認証サーバーにSSL(Secure Socket Layer)で接続するとき、電子証明書をクライアント(ブラウザ)に提示させて、接続元を認証する仕組み
ホスト名ネットワーク上でコンピューターを識別するための名前

あなたのWebサイトも、脅威に対する「安心」を手に入れませんか?

ふう、書き終えた

そういえば「卒論」と書かれたフロッピーが発掘されたんですが、どうすればいいんだろう。見るすべないなー。

ライター/もちゃじ

IT業界に縁なく秘書畑をさすらい、前職はインドで社長秘書。ほぼ日本語とパッションのみで乗り切ったずうずうしさはスキルの一つか。完全なインドア派ながらたまにふらりと旅に出る。行き場のない母性を持て余し、友人の犬を溺愛するもほえられる。体が硬く、インドでヨガティーチャーに笑われたことに深く傷つく一面も。

ITド素人の私がWebセキュリティについて学び、レベルアップしていく(予定です)様子をお届けします。学びを発信することで、少しでもWebセキュリティに関する「難しそう」というイメージが下がり、苦手意識のある方たちに届いたらうれしいです。

シェア ツイート

カテゴリー

キーワード