年末年始でセキュリティ分野を学習し、年明けにウェブ・セキュリティ基礎試験(通称:徳丸基礎試験)を受験することにしました。
そこで勉強した内容を備忘録としてまとめます。
今回はCSRF(クロスサイト・リクエストフォージェリ)について、概要や原因・一般的な対策をまとめます。
CSRFとは何なのか?
CSRFはユーザーの意図しない操作を攻撃者ができてしまう脆弱性です。
ブラウザの機能を悪用することで、認証済みでないとできないはずの重大な処理(送金や決済など)を、攻撃者が本人に成り代わってできてしまいます。
CSRF攻撃の流れ
オンラインバンキングを例にすると、CSRF攻撃は以下の流れで実行されます。
- ユーザーのセッションを利用:
ユーザーが攻撃対象のサイト(オンラインバンキング)にログインしている状態で、攻撃者はそのユーザーを自分の用意した別の罠ページに誘導します。 - 不正なリクエストの作成:
この罠ページには、対象のウェブサイト(オンラインバンキング)に対して行う不正な操作(お金を攻撃者の口座に送金するなど)を埋め込んだフォームやスクリプトが含まれています。 - 自動的なリクエスト送信:
ユーザーが罠ページを訪れると、そのフォームやスクリプトが自動的に実行され、ユーザーのブラウザはユーザーの知らない間に対象のウェブサイトに対して不正なリクエストを送信します。 - 攻撃対象サイトの誤認:
攻撃対象のウェブサイトは、このリクエストがユーザーのものであると誤認し、リクエストに従った操作(攻撃者の口座への送金)を実行します。
このようにCSRF攻撃はユーザーの既存のセッションを利用して不正な操作を行わせる攻撃です。
XSSとCSRFの違い
XSSとCSRFはどちらもユーザーの意図しない操作を引き起こす脆弱性である点では同じです。
CSRF攻撃は利用者のふりをして既存の処理を実行するため、既にサーバーサイドに存在している処理の悪用に限られます。
一方でXSSはサーバーからのレスポンスに含まれるスクリプトがブラウザ上で実行されることで攻撃が成立するため、ブラウザ上でできることであればスクリプト次第でどんな攻撃も可能です。
CSRFはどこでどうやって発生するのか?
CSRF攻撃はユーザーからのリクエストが本物かどうか、つまりそのユーザー自身が意図して実行したものかどうかを確認していない場合に発生します。
具体的には以下の箇所が発生源となりやすいです。
- クッキーのみでセッション管理が行われているサイト
- HTTP認証、TLSクライアント証明書のみで利用者の識別が行われているサイト
セッション管理とはWebサイトがユーザーのログイン状態を追跡する方法です。
しかしクッキーのみを使ってセッション管理をしていると、攻撃者はユーザーのブラウザに保存されているクッキーを悪用し、そのユーザーになりすまして操作ができてしまいます。
HTTP認証やTLSクライアント証明書はWebサイトがユーザーの身元を確認するための方法です。
しかしこれだけだと確認としては不十分なので、攻撃者に付け入る隙を与えてしまいます。
CSRF脆弱性が生まれてしまう背景
以下のWebの性質がCSRF脆弱性が生まれてしまう原因です。
- form要素のaction属性にはどのドメインのURLでも指定できる
- クッキーに保管されたセッションIDは、対象サイトに自動的に送信される
1つ目の性質により、罠サイトからでも攻撃対象のサイトにリクエストを送信できてしまいます。
2つ目の性質により、セッションIDはリクエストが罠サイトからだったとしても本物のユーザーからのリクエストだと誤解してしまい、攻撃者が意図した操作を実行してしまうのです。
CSRFはどうやったら防げるのか?
CSRF攻撃の防止策として以下の方法があります。
- CSRF対策の必要なページを区別する
- 正規利用者の意図したリクエストであることを確認する
- 処理の実行後に、登録済みメールアドレスに通知メールを送信する
根本的な対策となるのは1, 2だけで、3は保険的な対策となります。
1. CSRF対策の必要なページを区別する
まずはCSRF対策の必要なページとそうではないページの区別が必要です。
全てのページに対策が必要なわけではないからです。
アカウント情報の変更画面や決済ページなどは、外部からの悪意のあるリンクを通じて不正な操作を受ける可能性があるためCSRF対策を施すべきです。
一方でサービスの紹介ページや商品一覧ページはむしろ外部からリンクされて広くアクセスしてもらえた方が好都合なので対策すべきではありません。
このように、サービスにはCSRF対策をすべきページとそうではないページが混在しているため、まずはその区別が必要です。
2. ユーザーの意図したリクエストであることを確認する
CSRF対策が必要なページに対しては、そのページへのリクエストがユーザーの意図したものであるかを確認すべきです。具体的には次の3つの方法で確認が可能です。
- 秘密情報(トークン)の埋め込み
- パスワード再入力
- Refererのチェック
2.1 秘密情報(トークン)の埋め込み
リクエスト内に第三者が知り得ない秘密情報(トークン)を埋め込むことがCSRF対策の主流です。
そのトークンをアプリケーション側が要求すれば、リクエストにトークンが含まれているか否かでリクエストの正当性を判別できるからです。
トークンは乱数を用いて生成します。現在はフレームワークがトークン生成・チェックの機能を備えているケースも増えてきています。
2.2 パスワード再入力
処理を実行する最後の最後でパスワードの再入力を要求するのもCSRF対策として有効です。
これによりたとえ罠サイトから不正なリクエストが飛んできても、最後のパスワード入力が突破できず、攻撃が成立しません。
ただし闇雲に全ての画面にパスワード再入力を要求するのはユーザー体験に悪影響です。
だから事前にCSRF対策が必要なページを区別する必要があります。
2.3 Refererのチェック
HTTPリクエスト内のRefererの中身をチェックすることで正当なリクエストかどうかを判定できます。
正当なリクエストとCSRF攻撃によるリクエストではRefererフィールドの内容が異なるからです。
正当なリクエストでは信頼できるURL(実行画面の1つ手前のページのURLなど)がRefererとしてセットされています。
一方でCSRF攻撃の場合は罠サイトのURLなどが含まれており、ここで区別できるのです。
3. 処理の実行後に、登録済みメールアドレスに通知メールを送信する
上記の2つ以外の保険的な対策として、処理内容を通知するメールの送信が有効です。
攻撃を受けたユーザーがその事実に早く気づけるため、被害を最小限に抑えられるからです。
ただしメール自体には重要情報は含めず処理が実行された事実のみを記載すべきです。
通知メール自体ではCSRF攻撃を防げないが、被害の拡大を阻止するには一定の役割を果たせます。
まとめ
CSRFの概要と対策方法について理解できました。
コメント