Skip to content

MS_CSRFCountermeasures

nishi_74322014 edited this page Sep 11, 2026 · 2 revisions

CSRF(XSRF)対策の実装方針

概要

  • CSRF(XSRF) は利用中のブラウザから攻撃者により
    任意の認証済みリクエストを発生させる攻撃方法で、
    任意の情報の更新処理を送り付ける事が出来る。
  • ASP.NETでの CSRF(XSRF) 対策方針について纏める。

移行メモ(用語): CSRF = Cross-Site Request Forgery。
XSS(Cross-Site Scripting)と紛らわしいため、
Microsoft は XSRF と表記することが多い。

攻撃の本質は
**「ブラウザが Cookie を自動で送ってしまう」**ことにある。
ユーザーが罠サイトを踏むと、罠サイト上の form が
正規サイトへ POST し、ブラウザが正規サイトの Cookie を添えてしまう
サーバーから見ると正規の認証済みリクエストと区別がつかない。

対応方針の案

案件依存だが・・・。

フレームワーク毎の違い

  • POST
    ViewStateViewStateUserKey
    セッション ID を割り当てる方法がメジャー。
  • GET
    • 攻撃しやすいので QueryString で予期せぬ CRUD 等の操作がされないように作る。
    • 具体的には、画面の初期表示のみに GET を使用するなどする。
  • POST
    ValidateAntiForgeryToken 属性と Html.AntiForgeryToken ヘルパを使う。
  • GET: 同上。
  • 主に、業務系 SPA の裏の WebAPI は同様に対応が必要になる。
  • Cookie に設定した X-CSRF-TOKEN を、HTTP ヘッダに設定する方式が一般的。
  • ソレ以外の WebAPI は、client_id / client_secret の基本認証や
    bearer token を使用。

補足(なぜ Bearer トークンなら不要なのか): 最後の一文が要点で、
CSRF が成立するのは「ブラウザが自動で送る資格情報」を使う場合だけである。

認証方式 自動送信されるか CSRF 対策
Cookie(セッション) される 必要
Basic 認証 される(ブラウザが記憶していれば) 必要
Authorization: Bearer されない(JS が明示的に付ける) 不要

SPA で JWTlocalStorage に置き
ヘッダで送る構成が CSRF に強いのはこのためである
(ただし XSS には弱くなるというトレードオフがある)。

逆に「SPA だから安全」ではなく、
Cookie 認証を使う SPA では CSRF 対策が必要である。

判断材料

案件毎に CSRF(XSRF) 対策のポリシーを持って対応する必要がある。

診断ツールと診断結果

  • GET が通れば即、warning になるので診断ツールの誤検知が多い。
  • CSRF(XSRF) になっても実際に問題が起きるかどうかはアプリの作りによる。

攻撃対象サイト

一般的に、足がつかない、

  • 匿名アクセス可能なサイトか、
  • フリーメールサービスのアドレスでサインアップ可能なサイト

が多いと考える。

攻撃者の属性

  • 攻撃方法の特定
    • 匿名アクセスが可能なサイトの場合、誰でも攻撃可能。
    • 会員制サイトの場合、そのサイトを利用可能な会員でないと、
      攻撃方法を見い出せない。
  • 攻撃方法が解れば、攻撃自体は誰でも出来る。
  • しかし、最近は、SameSite属性の件の対策もあり、
    同一サイトでないと POST での攻撃も、し難くなって来ている。

補足(SameSite で状況が大きく変わった): 2020年以降、
Chrome の既定が SameSite=Lax になり、
CSRF の大部分が構造的に防がれるようになった。

SameSite クロスサイトの POST で Cookie が送られるか
Strict 送られない
Lax(現在の既定) 送られない(GET のトップレベル遷移のみ許可)
None; Secure 送られる

ただし、これだけに依存してはならない

  • 古いブラウザは SameSite を解釈しない
  • SameSite=None が必要な構成(form_post
    埋め込み iframe)では効かない
  • サブドメインは "same-site" 扱いevil.example.comwww.example.com は防げない)

多層防御として、トークン方式は引き続き実装すべきである。

SessionIDを使うのは非推奨の流れ。

  • セッション ID を CSRF トークンに使うべきでない。

補足(理由): CSRF トークンは HTML 内に出力されるため、

  • XSS があれば読み取られる
  • キャッシュや Referer から漏れうる

という経路がある。ここにセッション ID そのものを置くと、
CSRF の穴が即セッション ハイジャックに直結してしまう。

セッション ID とは別の乱数を生成し、
サーバー側でセッションと紐づけて検証するのが正しい。
ASP.NET Coreの Antiforgery は既定でこの実装である。

現在の実装(ASP.NET Core)

補足(Core での書き方): ASP.NET Coreでは
既定で有効になっている部分が多い。

対象 既定の挙動
Razor の <form> タグ ヘルパー 自動的に hidden の Antiforgery トークンを出力
[ValidateAntiForgeryToken] 個別に付与
[AutoValidateAntiforgeryToken] GET/HEAD/OPTIONS/TRACE 以外を自動検証(推奨)
[IgnoreAntiforgeryToken] 個別に除外
builder.Services.AddControllersWithViews(options =>
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));

全体に適用してから、必要な箇所だけ除外する方が
付け忘れによる漏れが起きないため安全である。

SPA + Cookie 認証の場合は、IAntiforgery からトークンを取得し、
Cookie に載せて JS がヘッダ(X-CSRF-TOKEN)で送り返す構成にする。

参考

Microsoft Learn


Tags: 移行, テスト, セキュリティ, ASP.NET

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally