【テクニカル・上級編】CSRF攻撃の基本メカニズムとステートレス/ステートフルな攻撃シナリオ – アプリケーションセキュリティ & 安全な開発防御ガイド

境界を越える意思、CSRFの深淵:ブラウザという「踏み台」の脆弱性再考

多くのエンジニアがCSRF(Cross-Site Request Forgery)を「古い脆弱性」と侮る。IPAのリストやOWASP Top 10で見飽きた名前だからだ。だが、現場でインシデントハンドリングを行っていると痛感するのは、この攻撃が依然として「認証」というセキュリティの最後の砦を、最もエレガントかつ泥臭く突破し続けているという事実だ。

CSRFの本質は、攻撃者が「ユーザーのブラウザ」をハッキングするのではなく、「ユーザーのブラウザが持つ『認証の自動解決メカニズム』」をハッキングすることにある。今回は、単なる対策の羅列ではなく、この攻撃がなぜ今日なお脅威であり続け、次世代アーキテクチャにおいてどう解釈すべきかを深掘りする。

—

1. 認証の自動解決:HTTPプロトコルの原罪

CSRFの根本原因は、HTTPのステートレス性に後付けされた「Cookie」という仕組みにある。ブラウザは、特定のドメインに対するリクエストが発生した際、そのドメインに関連付けられたCookieを、ユーザーの意思とは無関係に自動付与して送信する。

攻撃者はこれを利用する。ユーザーが bank.com にログインした状態で、攻撃者が用意した巧妙な罠サイト(evil.com)にアクセスさせる。罠サイト上の隠れた

タグや、fetch() を用いたリクエストが、ユーザーのブラウザを経由して bank.com へ送られる。このとき、ブラウザは「本人が送ったリクエスト」と区別できず、有効なセッションCookieを同梱してしまう。

攻撃シーケンスの低レイヤ的解剖

攻撃者は単にGETを叩くのではない。最近のアーキテクチャでは、JSONを期待するAPIエンドポイントが増えている。

// 攻撃者の罠サイトにおける巧妙なペイロード例
// 単純なGETではなく、Content-Typeを強制してプリフライトを誘発させつつ、
// 同期的なPOSTリクエストを偽装するケース
const data = { amount: 1000000, to: “attacker_account” };
fetch(‘https://bank.com/api/transfer’, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’
},
body: JSON.stringify(data),
credentials: ‘include’ // ここがポイント。ブラウザに強制的にCookieを載せさせる
});

このリクエストが成功するかどうかは、サーバー側のCORS設定とCookieの属性に依存する。しかし、多くの開発者は「CORSで許可していないから大丈夫」と過信し、結果として脆弱性を作り込む。

—

2. アーキテクトが設計すべき防衛層:防御の多層化

CSRF対策の王道は「リクエストに秘密のトークンを埋め込むこと」だが、現代のモダンなWebアプリケーション開発では、もっとエレガントな設計が必要だ。

A. SameSite属性によるプロトコルレベルの封じ込め

Cookieの SameSite 属性は、現在最も強力な防御壁だ。Strict または Lax を指定することで、クロスサイトからの自動的なCookie送信を制限できる。

セッションCookieの設定例
Set-Cookie: session_id=abc123xyz; Secure; HttpOnly; SameSite=Lax

Lax であれば、トップレベルのナビゲーション(リンククリックなど)ではCookieが送信されるが、サブリクエスト(や