ガイドSC

CSRF・SameSite・Origin/Referer検証・CSRF Token

公開: 2026-09-26更新: 2026-09-26
Cookie付きの状態変更要求を例に、SameSite、Origin・Referer、CSRF Tokenと復旧判断を学ぶ。

ログイン中の利用者が別サイトを開いたとき、そのサイトから送られた要求にログインCookieが添付される場合があります。送金先の変更やメールアドレス変更をWebアプリがCookieだけで許可すると、誰の意思による操作かを区別できません。この記事では架空のhttps://pay.example/account/emailを例に、CSRF、SameSite、Origin・Referer検証、CSRF Tokenの役割を追います。

科目B(午後)では、ブラウザが送れることと攻撃者が応答を読めることを分けます。CookieのSameSite属性は条件付きの防御であり、Token・要求元検証・利用者認可とは役割が異なります。以下のドメイン、利用者、ログは教材用の架空例です。

1. 誰が要求を作り、誰の資格情報が付くか

被害者aliceはpay.exampleにログイン済みで、ブラウザにはsession Cookieがあります。攻撃者はevil.exampleのHTMLを配布でき、aliceに開かせます。pay.exampleはPOST /account/emailで登録メールを更新します。攻撃者はaliceのCookie値を知らなくても、ブラウザにクロスサイト要求を送らせることを狙います。

用語

この例での意味

CSRF

Cross-Site Request Forgery。攻撃者のページから、被害者のブラウザに別サイトpay.exampleへの状態変更要求を送らせる攻撃。サーバが『Cookie付きなら本人の意思』と判断することが問題になる。

Cookie

pay.exampleが発行したsession識別子。ブラウザはドメイン、Path、Secure、SameSiteなどの条件に従って自動送信する。攻撃者のスクリプトがCookie値を読める必要はない。

Same-Origin Policy

異なるオリジンからの応答読取りなどを制限するブラウザの仕組み。単純なフォーム送信など、クロスオリジン要求の送信そのものを一律に止める仕組みではない。

SameSite

Cookieがクロスサイト要求へ添付される条件を制御する属性。Strict、Lax、Noneの意味を区別する。『同じサイト』と『同じオリジン』は異なり、同一サイト内の別サブドメインには注意する。

Originヘッダ

ブラウザが対応する要求で送る、要求元のスキーム・ホスト・ポート。pay.exampleがhttps://pay.exampleと一致するか確認する。存在しない場合やnullの場合の扱いを定める。

Refererヘッダ

要求元ページのURLを示す場合がある。プライバシー設定やReferrer-Policyで欠落・短縮され得るため、常に完全なURLがある前提にしない。

CSRF Token

サーバがセッションに結び付け、攻撃者が推測できない値。フォームの隠し項目又は同一オリジンのスクリプトが付けるヘッダで送る。サーバは状態変更前に一致と有効性を確かめる。

認証・認可

Cookieでaliceを識別することが認証、aliceが自分のメールを変更できるかが認可。CSRF対策は、要求が本人の正規画面から来たかを検証する追加の判断。

この例ではセッションCookieがSameSite=None; Secureで設定されていると仮定します。したがってブラウザは条件を満たすクロスサイト要求にCookieを付け得ます。SameSite=LaxやStrictなら挙動が違うため、設問のCookie属性を先に確かめます。

攻撃ページからのメール変更要求攻撃者はCookie値を読まない。ブラウザが対象サイトの条件に従って送る。攻撃者サイトaliceのブラウザpay.example1. evil.exampleを開く2. 偽フォームを返す3. Cookie付きPOST4. 検証後に拒否
攻撃ページからのメール変更要求

攻撃者はCookie値を読まない。ブラウザが対象サイトの条件に従って送る。

図の最後は対策が有効な構成での拒否です。Cookieの認証だけに依存する脆弱な実装なら、第三段階のPOSTでメールが変更され得ます。攻撃者が応答本文を読めないとしても、状態変更は成功し得る点がCSRFの核心です。

2. 正常なPOSTと攻撃者起点のPOSTを比較する

正規の画面では、pay.exampleのサーバがaliceのセッションに結び付いたTokenを発行し、フォームに入れます。aliceが送信したとき、ブラウザはCookieとTokenを送り、サーバが認証・認可・Token・要求元を確認してからメールを変更します。

text
POST /account/email HTTP/1.1
Host: pay.example
Origin: https://pay.example
Cookie: session=<省略>
Content-Type: application/x-www-form-urlencoded

email=alice%40new.example&csrf_token=T-alice-7

判定: session=alice、token=一致、origin=一致
結果: メール変更を許可

T-alice-7は説明用の値で、実際には推測困難な乱数又は安全な署名付き方式の値を使います。TokenをURLに入れると履歴・Referer・ログへ漏れる可能性があるため、フォーム本文や適切なヘッダで送ります。Cookieに入れるだけのTokenを無条件に信頼しても、Cookieは自動送信されるので防御になりません。

2-1. SameSiteの三つの値

設定

この操作への意味と限界

Strict

クロスサイトからの要求にはCookieを付けない。保護は強いが、外部リンクからの遷移でログイン状態が見えないなどの業務影響があり得る。

Lax

クロスサイトの通常のトップレベル遷移で、安全なメソッドへのCookie送信を許す。通常のクロスサイトPOSTには付けない。ただしブラウザの既定値や例外、GETで状態変更する実装を考慮する。

None; Secure

クロスサイトへのCookie送信を許す構成。SSOや埋込みで必要な場合があるが、状態変更APIにはTokenや要求元検証を必ず設ける。SecureはHTTPS送信条件でありCSRF防止そのものではない。

同一サイトの別サブドメイン

evil.exampleとは違い、攻撃者がpay.exampleと同じ登録可能ドメイン配下のサブドメインを支配する場合、SameSite判定では同じサイトになり得る。Originの完全一致とTokenが重要。

SameSiteは『サイト』の境界で、Originはスキーム・ホスト・ポートの境界です。https://blog.pay.exampleとhttps://pay.exampleは同じサイトとして扱われ得ても同一オリジンではありません。サブドメインを委託先や利用者が管理する場合、SameSiteだけで守る設計は危険です。

2-2. Cookie属性を変える前に業務の経路を見る

pay.exampleに外部決済画面から戻る導線がある場合、SameSite=Strictではトップレベル遷移時にセッションCookieが送られず、利用者がログアウトしたように見えることがあります。Laxなら安全なトップレベル遷移でCookieが送られる場合があります。Noneはクロスサイトの埋込み等を必要とする構成で使われます。各画面の実際の遷移とCookieを確認します。

SameSiteを省略したCookieのブラウザ既定値は実装・時期で変わり得ます。特に既定のLax相当動作には短時間のPOST例外を持つブラウザがあります。『設定していないからLaxに違いない』『LaxだからPOSTでは絶対送られない』と決めず、明示したCookie属性と対象ブラウザで試験します。

要求の場面

CookieとCSRFの判断

evil.exampleからの通常フォームPOST

この例のSameSite=Noneならsessionが添付され得る。TokenとOrigin検証を行わないAPIは危険。

evil.exampleからのトップレベルGET

LaxでもCookieが添付され得る。GETで状態を変えない設計が必要。

blog.pay.exampleからpay.exampleへの要求

両ホストが同じサイト扱いでもオリジンは異なる。サブドメインに攻撃者がいる条件では、Origin完全一致とTokenが必要。

pay.example内の正規フォーム

正規のCookie、Origin、Tokenがそろう。本人の操作かどうかの業務監査や重要操作の再認証は別途考える。

3. Origin・Referer・Tokenはどこで検証するか

防御

適用位置と判断条件

Origin検証

状態変更APIのサーバで、Originが期待するhttps://pay.exampleと一致するか確認する。Hostの部分一致ではなく、スキーム・ホスト・ポートを含むオリジンで比較する。リバースプロキシ越しの公開オリジンは信頼できる設定から決める。

Referer検証

Originがない場合の補助にできる。完全一致又は同一オリジンを安全なURLパーサで確認し、pay.example.evil.exampleのような前方一致を受け入れない。欠落時の方針を事前に決める。

Synchronizer Token

サーバ側セッションに紐付く予測不能値と要求値を照合する。攻撃者ページは同一オリジンのフォーム値を読めない前提で、値の推測・再利用・漏えいに注意する。

署名付きDouble Submit Cookie

Cookie値と要求パラメータの一致だけでは、Cookieを注入できる条件で弱い。セッションに結び付いた署名付きTokenを検証する方式なら、その危険を抑えられる。

Fetch Metadata

Sec-Fetch-Siteなどのブラウザヘッダで要求の文脈を追加判断できる。古いクライアントや欠落時の動作を定め、Token・認可の代わりにしない。

再認証・操作確認

送金先変更のような重要操作で追加認証や変更通知を設ける。CSRFが成立しても被害を抑える防御であり、APIのToken検証自体を省かない。

OriginとRefererは、通常のブラウザからの要求では攻撃者ページのJavaScriptが自由に偽装できないヘッダです。ただし非ブラウザのHTTPクライアントは任意のヘッダを送れるため、これらはログイン済み利用者本人の認証・認可を代替しません。欠落・nullを無条件で許可すると、検証を迂回する経路が残ります。

TokenをGET /account/emailのHTMLに含める場合、その画面を外部サイトのスクリプトが読めないようにする境界が前提です。XSSでpay.example上のスクリプト実行を許すと、攻撃者がTokenを読んだり正規画面から操作したりできるため、XSS修正も必要です。

3-1. Tokenの生成・配布・失効

Synchronizer Token方式では、サーバが十分な乱数からTokenを生成し、セッションに結び付けます。画面に配布し、POSTで受け取り、比較した後に業務更新を行います。ログアウトやセッション再生成時に旧Tokenをいつ無効化するか、複数タブや戻る操作でどう扱うかを設計します。

すべてのPOSTで毎回Tokenを更新すると、並行する複数タブや再送で正規要求が拒否される場合があります。セッション単位Tokenや操作単位Tokenを選び、リプレイ防止が必要な高リスク操作では別の一回限り確認を設けます。Tokenの有効期間と再発行の設計は、CSRF防止と利用者の操作性の両方を見ます。

Double Submit方式では、Cookieの値と本文・ヘッダの値を比較します。サーバがセッションに結び付いた署名を検証せず、単なる一致だけを見れば、攻撃者がCookieを注入できる環境で弱くなります。CookieのDomain属性、サブドメイン管理、署名鍵の保護を確認します。

Token設計

検証の要点

値の生成

推測困難な乱数を使う。連番や利用者IDをそのままTokenにしない。

セッションへの結合

aliceのTokenをbobのセッションで受け入れない。ログイン・ログアウトやセッション固定対策の後に有効性を確認する。

転送場所

フォーム本文又は同一オリジンのスクリプトが付けるヘッダに入れる。URLやサーバログ、外部Refererへ漏らさない。

検証順

状態変更前に認証・認可・Token・要求元を確認する。失敗時は副作用を残さず拒否し、Tokenの生値をログへ出さない。

3-2. CORSやJSONはCSRF防御か

CORSは主にブラウザが異なるオリジンの応答を読み、特定のクロスオリジン要求を送る条件を扱います。単純なHTMLフォームで送れる状態変更要求が残っていれば、CORSの読取り制限だけではCSRFを防げません。JSON APIでカスタムヘッダを必須にするとプリフライトが必要になりますが、サーバ側でContent-TypeとToken・Originを厳格に確認します。

GET /account/email?new=...のような状態変更を実装してはいけません。SameSite=LaxではクロスサイトのトップレベルGETにCookieが付くため、リンクを踏ませるだけで変更できる恐れがあります。HTTPの安全なメソッドの意味とアプリの実装を一致させます。

3-3. リバースプロキシ越しの要求元確認

公開入口でTLSを終端し、内部アプリへHTTPで転送する構成では、内部アプリから見た接続先がhttp://10.0.2.20のような値になる場合があります。Originの比較先をその内部URLから組み立てると、正規のhttps://pay.exampleも誤拒否します。公開オリジンを安全な設定として持ち、信頼できるプロキシの情報だけを使います。

攻撃者が送ったX-Forwarded-HostやX-Forwarded-Protoをそのまま比較先に使うと、期待するオリジンを攻撃者側へ変えられる恐れがあります。公開入口で外部入力を破棄・再設定し、アプリは信頼する入口からの値だけを採用します。Origin自体の完全一致判定と、比較先の真正性を分けます。

4. 架空ログを読み、どこで拒否したか示す

以下は架空の正常要求と攻撃要求です。時刻はUTC、Tokenは記録せず照合結果だけを残しています。Cookieの生値もログに含めていません。

text
10:00:00 app req=C1 method=POST path=/account/email
  user=alice origin=https://pay.example
  token=valid samesite_cookie=None action=allow
10:04:00 app req=C2 method=POST path=/account/email
  user=alice origin=https://evil.example
  token=missing samesite_cookie=None action=deny
  reason=origin_mismatch

行

確認できること・できないこと

C1 allow

aliceのセッションでOriginとTokenが一致し、サーバが操作を許可した。本人が意図的に操作したかは画面操作や本人確認の証拠も要る。

C2 user=alice

Cookieによりaliceのセッションとして識別された。要求の起点はevil.exampleなので、aliceの意思による要求とは言えない。

C2 token=missing

Tokenがない。これだけで攻撃者がTokenを知る可能性ゼロとは言えないが、この要求はToken防御でも拒否できる。

C2 deny

この要求はアプリの要求元検証で拒否された。別のAPIやGETによる状態変更経路が残っていないかは追加調査が要る。

C2の拒否ログは、この一件の変更が阻止された証拠です。攻撃ページへの訪問、別のエンドポイントでの成功、過去の変更履歴までは確定しません。メール変更履歴、通知、セッションの発行記録を合わせて調べます。

5. 攻撃条件・例外・復旧

Cookie依存APIへのCSRFCookieが付く条件と、要求元・Tokenを検証しない条件が重なると成立する。1利用者がログイン2攻撃ページを開く3ブラウザがPOST4サーバが変更
Cookie依存APIへのCSRF
  1. 1. 利用者がログイン:証跡 セッション発行/防御・対処 Cookie属性を設計
  2. 2. 攻撃ページを開く:証跡 ブラウザ履歴/防御・対処 重要操作を確認
  3. 3. ブラウザがPOST:証跡 OriginとCookie条件/防御・対処 OriginとTokenを検証
  4. 4. サーバが変更:証跡 業務変更ログ/防御・対処 認可と追加認証

Cookieが付く条件と、要求元・Tokenを検証しない条件が重なると成立する。

攻撃成立には、被害者がログイン済みで、Cookieが要求へ付く条件、攻撃者から送れる要求形式、サーバがTokenや要求元を正しく検証しないことが必要です。攻撃者がCookie値やレスポンス本文を読める必要はありません。反対にSameSite=Laxの通常のクロスサイトPOSTでCookieが付かない環境なら、この経路だけでは成立しません。

  1. 状態変更APIを棚卸しし、GETで変更している箇所を安全なメソッド設計へ修正する。

  2. 公開オリジンに対するOrigin検証と、セッションに結び付いたToken検証をサーバで行う。Cookieには用途に合うSameSiteとSecureを設定する。

  3. 正常フォーム、evil.example起点のフォーム、Origin欠落・null、Token欠落・不一致、同一サイト別サブドメインをテストする。

  4. 不正変更があった場合は履歴を確認し、本人確認の上で元に戻す。攻撃者が取得した新しい認証手段やセッションがあれば無効化する。

正当なSSOや埋込み画面がクロスサイトCookieを必要とする場合、SameSite=Strictへ一律変更すると業務が止まります。例外となる経路を限定し、Token・Origin、必要なら追加認証で保護します。変更後は正常経路と攻撃経路を両方試します。

5-1. 事故後にメール変更が成功していた場合

変更先が攻撃者のアドレスなら、パスワード再設定メールなどを受け取られた可能性があります。変更時刻、通知メール、再設定操作、ログイン元を照合し、本人確認の上でメールを戻します。既に発行された再設定トークンやセッションを無効化する必要があるかも確認します。

攻撃を受けた本人の操作だけを巻き戻すのではなく、同じAPIの変更履歴から他の被害者を探します。修正後はCookie属性、Token、Origin、欠落ヘッダ、GET状態変更、同一サイト別サブドメインの各条件を再試験します。

6. 科目B(午後)の記述演習

演習1:SOPと送信

条件:evil.exampleはpay.exampleの応答本文を読めないが、aliceのブラウザでメール変更フォームを送信できた。問い:CSRFが成立し得る理由を述べよ。

解答:SOPの応答読取り制限はフォーム送信とサーバ側の状態変更を一律に禁止しない。Cookieが付いてサーバがToken等を確認しなければ変更され得る。誤答『応答を読めないので変更もできない』は送信と読取りを混同する。

演習2:SameSite=LaxとGET

条件:session CookieはSameSite=Laxで、GET /account/email?new=...が状態変更する。問い:攻撃経路を述べよ。

解答:攻撃者がそのURLへトップレベル遷移させると、LaxのCookieが付く可能性があり変更が起きる。GETによる状態変更をやめ、状態変更APIでToken等を検証する。誤答『Laxなので全クロスサイト要求でCookieが付かない』は条件を誤る。

演習3:Origin欠落時

条件:Originがない要求を無条件で許可する実装になっている。問い:追加で決めるべき方針を述べよ。

解答:欠落・null時は拒否を基本に、必要な正規クライアントだけを識別してTokenやRefererの妥当性を確認する。誤答『Originがないので同一オリジン』は観測の欠落を一致と誤解する。

演習4:TokenがCookieにだけある

条件:サーバはCookieのcsrf_tokenがあるかだけを確認し、本文やヘッダとの照合はない。問い:弱い理由を述べよ。

解答:Cookieはブラウザが自動送信するため、攻撃要求にも一緒に付く。別の経路で送る予測不能Tokenとセッションの結合を検証する。誤答『CookieにTokenがあれば本人操作』は自動送信を見落とす。

演習5:同一サイト別サブドメイン

条件:攻撃者がblog.pay.exampleを管理し、pay.exampleと同じ登録可能ドメイン配下にある。問い:SameSiteだけに頼れない理由を述べよ。

解答:両者が同一サイト扱いになりCookieが送られ得る。pay.exampleの完全なOrigin確認とToken検証を行う。誤答『別ホストなので必ずクロスサイト』はサイトとオリジンを混同する。

演習6:信頼できない転送ヘッダ

条件:アプリがX-Forwarded-Hostを信じてOriginとの比較先を作り、公開入口は外部からの同名ヘッダを通す。問い:修正位置を述べよ。

解答:公開入口で外部の転送ヘッダを破棄して再設定し、アプリは固定された公開オリジン又は信頼済み入口の値を使う。誤答『Originの文字列比較だけ直せばよい』は比較先自体が偽装可能な点を見落とす。

7. 一次資料

OWASP:Cross-Site Request Forgery Prevention Cheat Sheet

WHATWG Fetch Standard:Originとクロスオリジン要求

RFC 9110:安全なメソッドの意味

MDN:SameSite Cookieの送信条件

この記事についてAIに深掘り質問する

ChatGPT、Claude、Perplexityにこの記事を参照させ、要点の確認や疑問点を自由に質問できます。

次におすすめの学習

編集・検証について

編集・検証:IT資格ラボ編集部

IPAが公開する試験要綱・シラバス・過去問題と、各技術の公式資料を優先して内容を確認しています。制度変更や誤りを確認した場合は、記事を見直して更新します。

編集方針・情報源・訂正方針を見る
この記事を共有する