1. JWTの保存先問題:LocalStorageという脆弱な設計

問題の本質

JWTはBearerトークンであり、次の性質を持ちます。トークンを保持している者が、そのままユーザー本人として認識されるLocalStorageに保存する場合の問題は以下です。

JavaScript → LocalStorageにアクセス可能

・XSS → JavaScriptを実行可能

・結果 → トークンが窃取される

 

保存方法の比較

推奨設計

Set-Cookie:

・HttpOnly

・Secure

・SameSite=Strict

 

フロー

ログイン

→ サーバがCookie発行

→ ブラウザが自動送信

→ APIで認証

 

JavaScriptからトークンを完全に隔離することが重要です。

 

2. XSS:フロントエンドが攻撃媒体になる瞬間

攻撃メカニズム

ユーザー入力

→ スクリプト注入

→ ブラウザで実行

→ Cookie / セッション情報の窃取

 

誤解されがちな点

・Reactは安全という誤認

dangerouslySetInnerHTMLの安易な使用

 

これらは防御を無効化します。

 

多層防御(Defense in Depth)

フロントエンド

HTMLエスケープ

・危険なAPIの使用回避

 

バックエンド(CSP)

 

CSPの動作

スクリプト読み込み

→ CSPポリシーと照合

→ 不一致なら実行拒否

 

XSSが成立しても、実行を防ぐ最後の防壁になります。

 

3. CSRF:Cookie採用時に再浮上する脅威

よくある誤解

JWTを使えばCSRFは不要という認識は誤りです。

 

Cookieを使う場合、CSRFは依然として有効な攻撃手法です。

 

攻撃フロー

ユーザーがログイン(Cookie保持)

→ 攻撃サイトにアクセス

→ 悪意のリクエスト送信

→ ブラウザが自動でCookie付与

→ サーバが正規リクエストと誤認

 

対策:Double Submit Cookie

サーバ:

  CookieにCSRFトークンを保存

 

フロントエンド:

  トークンをヘッダーに付与

 

サーバ:

  Cookieとヘッダーを比較

 

Spring実装

CookieCsrfTokenRepository.withHttpOnlyFalse() 

 

フロントエンドがトークンを取得できる必要があります。

 

4. CORS設定:過剰な許可が招くリスク

危険な設定

allowedOrigins("*") 

 

これは事実上、すべてのオリジンにAPI利用を許可することを意味します。

 

CORSの動作

リクエスト送信

→ Origin確認

→ サーバが許可判定

→ 条件一致でアクセス許可

 

適切な設定

 

configuration.setAllowedOrigins(List.of("https://app.example.com"));

configuration.setAllowCredentials(true);

 

 

 

誤設定によるリスク

5. バリデーション:責務の誤解が招く脆弱性

根本問題

フロントエンドのバリデーションはセキュリティではありません。

 

攻撃の実態

攻撃者

→ APIを直接呼び出し

→ UIを完全にバイパス

 

正しい責務分離

・フロントエンド: UX改善

・バックエンド: セキュリティ

 

 

Springでの実装

@Valid

@NotNull

@Size(max = 50)

 

重要:所有権チェック

ユーザーAが /users/2 にアクセス

→ 本人かどうか検証

 

これを怠るとIDORが発生します。

 

6. 秘密情報の漏洩:ビルド成果物の盲点

問題

フロントエンドのバンドルは公開資産です。

JSファイル取得

→ 内容解析

→ APIキーや内部情報の抽出

 

対策:DTOパターン

Entity → DTO → JSON

 

必要最小限の情報のみ返却します。

危険な例

内部情報の露出は重大なリスクです。

 

7. サプライチェーン攻撃:外部依存という攻撃経路

問題の構造

依存ライブラリが侵害

→ アプリに組み込まれる

→ 悪意コード実行

 

対策

フロントエンド

npm audit

・Snyk

 

バックエンド

OWASP Dependency Check

 

SRIの活用

<script src="..." integrity="sha384-xxx"></script>

 

改ざんされたスクリプトの実行を防ぎます。

 

本稿で取り上げた各脆弱性は独立した問題ではなく、すべてが相互に関連しながら連鎖的にシステムの安全性に影響を与えます。JWTの保存方法、XSS対策、CSRF防御、CORS制御、バリデーション、データ出力、依存関係管理のいずれか一つでも欠けると、全体の防御は成立しません。したがって重要なのは、個別の技術を適用することではなく、「フロントエンドは常に非信頼である」という前提に基づき、多層的かつ一貫したアーキテクチャを設計することです。セキュリティは後付けの機能ではなく、システム設計そのものであるという認識こそが、実践的な防御の出発点となります。