SPAでCSRF対策が軽視されやすい理由とSameSite Cookieの影響
SPAのセキュリティを考えるとき、多くの開発者はXSSやトークン漏洩には敏感になります。しかしCSRF(クロスサイトリクエストフォージェリ)は後回しにされがちです。
理由は単純で、「トークン認証を使っているから大丈夫」と思われやすいからです。ところが実際には、SPAでもCSRFは成立します。むしろ構成によっては気づきにくくなります。
CSRFとはどんな攻撃か
CSRFは「ユーザーの意思とは無関係に、認証済みの操作を実行させる攻撃」です。典型例は次のようなものです。
ユーザーが銀行サイトにログインしたまま、別のサイトを開いたとします。そのサイトに次のコードが埋め込まれていた場合です。
<img src="https://bank.example/transfer?to=attacker&amount=100000">
ブラウザは単なる画像読み込みとしてリクエストを送ります。しかしCookieは自動送信されます。結果として送金処理が実行されます。
ここで重要なのは、ユーザーがクリックすらしていない点です。ブラウザの「自動Cookie送信」が攻撃の成立条件になります。
なぜSPAでは問題が見えにくいのか
SPAではAPI呼び出しはJavaScriptで行われます。
fetch("/api/profile", { method: "POST" });
このため「フォーム送信がない=CSRFはない」と誤解されがちです。しかしブラウザがCookieを送信するかどうかは、フォームかJavaScriptかではなく、オリジンとCookie属性で決まります。
もしAPIがCookie認証を使っている場合、外部サイトからでもリクエストは送られます。
SameSite Cookieとは何か
この問題に対処するために導入されたのがSameSite属性です。
Set-Cookie: SESSION=abc123; SameSite=Lax
SameSiteは「他サイトからのリクエストにCookieを付与するか」を制御します。
| 設定 | 挙動 |
| Strict | 他サイトからは一切送らない |
| Lax | 通常の遷移のみ送る |
| None | 常に送る(Secure必須) |
近年のブラウザでは、未指定のCookieはLaxとして扱われます。これにより多くの単純なCSRFは防がれます。
SPA特有の落とし穴
ここで問題が発生します。SPAでは次の構成がよくあります。
- フロント:app.example.com
- API:api.example.com
この場合、同一サイトでも「別オリジン」です。Cookie送信にはSameSite=Noneが必要になります。
Set-Cookie: SESSION=abc123; SameSite=None; Secure
つまりCSRF防御を弱めないとログインが維持できません。この時点でCSRFのリスクが復活します。
よくある誤解:Authorizationヘッダなら安全?
BearerトークンをAuthorizationヘッダに入れていれば安全だと考えられがちです。確かに外部サイトはヘッダを自由に付与できません。
しかし次の条件では成立します。
- トークンをCookieに保存
- 自動送信
- APIがCookie認証を併用
この場合、CSRF攻撃が可能になります。トークン方式とCookie方式が混在すると、想定外の挙動になります。
対策:CSRFトークン
基本対策はCSRFトークンです。サーバはランダム値を発行し、フォームやリクエストヘッダに含めさせます。
fetch("/api/update", { method: "POST", headers: { "X-CSRF-Token": token } });
攻撃者はこの値を取得できないため、正規リクエストを偽装できません。
なぜSameSiteだけでは不十分か
SameSiteは強力ですが万能ではありません。
- サブドメイン構成
- OAuthリダイレクト
- 古いブラウザ
これらでは例外設定が必要になります。その瞬間、防御が弱まります。実務ではSameSiteとCSRFトークンを併用するのが一般的です。
実務で起きやすい事故
SPA移行時に多い問題があります。
- 開発環境では動く
- 本番の外部連携で壊れる
- SameSite=Noneへ変更
- CSRF対策未実装
この流れで脆弱性が入り込みます。特に決済や設定変更APIで危険です。
まとめ
SPAでCSRFが軽視されやすいのは、画面遷移やフォーム送信が減るため攻撃のイメージが湧きにくいからです。しかし本質は「Cookieが自動送信されるかどうか」です。
SameSite Cookieは強力な防御ですが、クロスオリジン構成のSPAでは例外設定が必要になり、リスクが戻ります。最終的にはCSRFトークンとの併用が安全です。
セキュリティ対策は単独では成立しません。認証方式・Cookie属性・ブラウザ挙動を一体として設計すると、後からの修正が大きく減ります。