メインコンテンツまでスキップ

OAuth 2.0 / OIDC 攻撃パターン

OAuth 2.0 と OpenID Connect における代表的な攻撃パターンとその対策をまとめます。


第1部: 認可フロー関連の攻撃

CSRF(Cross-Site Request Forgery)攻撃

攻撃者が被害者のブラウザを使って不正な認可を完了させる攻撃。

攻撃シナリオ:

1. 攻撃者が自分のアカウントで認可フローを開始
2. 認可コードを取得するが、使用しない
3. 被害者に偽の callback URL を踏ませる
https://rp.example.com/callback?code=ATTACKER_CODE
4. 被害者のブラウザで攻撃者の認可コードが使用される
5. 被害者のセッションが攻撃者のアカウントに紐付けられる

結果:
被害者が攻撃者のアカウントで操作
→ 被害者の入力データが攻撃者に送られる

対策:

1. state パラメータを使用
- 認可リクエスト時にランダムな state を生成
- コールバック時に state を検証
- セッションに紐付けて管理

2. PKCE を使用(推奨)
- state に加えて PKCE を使用
- code_verifier はクライアントのみが知っている

認可コード横取り攻撃

悪意のあるアプリケーションが認可コードを傍受する攻撃。

攻撃シナリオ(モバイル):

1. 正規アプリと同じカスタム URL スキームを登録した悪意のアプリ
2. ユーザーが正規アプリで認可を開始
3. 認可コードが悪意のアプリに渡される
4. 悪意のアプリがトークンを取得

┌──────────────┐ code ┌──────────────┐
│ 悪意のアプリ │ ◄─────────── │ Browser │
│ │ │ │
│ │ ── code ────► │ 認可 │
│ │ │ サーバー │
│ │ ◄── token ── │ │
└──────────────┘ └──────────────┘

対策:

1. PKCE を必須にする
- 悪意のアプリは code_verifier を知らない
- トークン交換が失敗する

2. App Links / Universal Links を使用
- ドメイン所有者のみがリンクを登録可能
- カスタム URL スキームより安全

リダイレクト URI 操作

攻撃者が redirect_uri を操作してトークンを盗む攻撃。

攻撃パターン:

1. オープンリダイレクト
redirect_uri=https://rp.example.com/callback?next=https://evil.com

2. パス操作
redirect_uri=https://rp.example.com/callback/../evil

3. サブドメイン
redirect_uri=https://evil.rp.example.com/callback

4. 異なるポート
redirect_uri=https://rp.example.com:8443/callback

対策:

1. 完全一致での検証
- 登録された redirect_uri と完全一致
- パターンマッチングは避ける

2. 正規化後の比較
- URL を正規化してから比較
- パストラバーサルを防止

3. クエリパラメータの扱い
- 登録時にクエリパラメータを禁止
- または完全一致で検証

Mix-Up 攻撃

複数の認可サーバーを使用するクライアントを狙った攻撃。

攻撃シナリオ:

1. クライアントが AS-1 と AS-2 をサポート
2. ユーザーが AS-1 で認可を開始
3. 攻撃者が認可レスポンスを操作
- AS-2 の認可コードを AS-1 のコードとして送信
4. クライアントが AS-1 にトークンリクエスト
5. AS-1 はエラーを返すが、認可コードは漏洩

┌────────┐ AS-2 の code ┌────────┐
│ Client │ ◄────────────── │ 攻撃者 │
│ │ │ │
│ │ ── AS-2 code ─► │ AS-1 │ ← コード漏洩
└────────┘ └────────┘

対策:

1. RFC 9207 の iss パラメータ
- 認可レスポンスに iss を含める
- 期待される issuer と比較

2. state に issuer を含める
- state をデコードして issuer を取得
- レスポンスの送信元と比較

第2部: トークン関連の攻撃

トークン漏洩

アクセストークンやリフレッシュトークンが漏洩する攻撃。

漏洩経路:

1. ログファイル
- トークンがログに記録される
- エラーメッセージにトークンが含まれる

2. Referer ヘッダー
- クエリパラメータにトークンがある場合
- 外部リンクで Referer として送信

3. ブラウザ履歴
- 暗黙的フローでフラグメントにトークン
- URL バーに表示される

4. クライアント側の保存
- localStorage への保存
- XSS で盗まれる可能性

対策:

1. 認可コードフローを使用
- トークンは URL に含まれない
- POST レスポンスで取得

2. DPoP を使用
- トークンを特定の鍵にバインド
- 盗まれても他者は使用できない

3. mTLS を使用
- トークンをクライアント証明書にバインド
- 証明書なしでは使用不可

4. 短い有効期限
- アクセストークンを短く(数分〜数時間)
- 漏洩時の影響を限定

トークン置換攻撃

正当なトークンを別の文脈で不正使用する攻撃。

攻撃シナリオ:

1. Resource A 用のトークンを取得
2. Resource B にトークンを送信
3. Resource B が誤ってトークンを受け入れる

┌────────┐ Token (for A) ┌────────┐
│ 攻撃者 │ ─────────────────► │ Res B │
│ │ │ │
│ │ ◄── 認可成功 ────── │ ✓? │
└────────┘ └────────┘

対策:

1. audience の検証
- JWT の aud クレームを検証
- 自分宛てのトークンのみ受け入れ

2. RFC 8707 Resource Indicators
- リソースごとにトークンを発行
- 別のリソースでは無効

リプレイ攻撃

傍受したトークンやアサーションを再利用する攻撃。

攻撃シナリオ:

1. 攻撃者がネットワークトラフィックを傍受
2. 正当なトークンリクエストを記録
3. 同じリクエストを後で再送

┌────────┐ 傍受したリクエスト ┌────────┐
│ 攻撃者 │ ─────────────────► │ AS │
│ │ │ │
│ │ ◄── Token ──────── │ │
└────────┘ └────────┘

対策:

1. jti クレーム
- JWT に一意識別子を含める
- 使用済み jti をキャッシュ

2. 短い有効期限
- exp を数分に設定
- リプレイの時間窓を短縮

3. TLS
- 通信を暗号化
- 傍受を防止

第3部: クライアント関連の攻撃

クライアント偽装

攻撃者が正規のクライアントになりすます攻撃。

攻撃シナリオ:

1. 公開クライアント(パブリッククライアント)の client_id を取得
2. 攻撃者のアプリで同じ client_id を使用
3. ユーザーを騙して認可させる

対策:
- 機密クライアントはクライアント認証を必須
- パブリッククライアントは PKCE を必須
- redirect_uri の厳格な検証

クライアント認証情報の漏洩

client_secret などの認証情報が漏洩する攻撃。

漏洩経路:

1. ソースコードへのハードコード
- GitHub などで公開

2. 設定ファイル
- .env ファイルの誤公開

3. ログ
- Basic 認証ヘッダーのログ記録

4. サプライチェーン攻撃
- 依存ライブラリ経由での漏洩

対策:

1. private_key_jwt を使用
- client_secret の代わりに非対称鍵
- 秘密鍵は送信されない

2. mTLS を使用
- クライアント証明書で認証
- 証明書の秘密鍵は送信されない

3. シークレット管理
- HashiCorp Vault などを使用
- 環境変数やファイルに直接保存しない

4. ローテーション
- 定期的に client_secret を更新
- 漏洩時の影響を限定

第4部: その他の攻撃

オープンリダイレクター

認可エンドポイントをオープンリダイレクターとして悪用する攻撃。

攻撃シナリオ:

1. 攻撃者が不正な redirect_uri で認可リクエストを作成
https://as.example.com/authorize?
client_id=valid_client
&redirect_uri=https://evil.com/callback
&response_type=code

2. ユーザーが信頼する AS のドメインを見てクリック
3. 認可後、ユーザーが evil.com にリダイレクト
4. フィッシングサイトで認証情報を盗む

対策:

1. redirect_uri の事前登録必須
2. 完全一致での検証
3. ワイルドカードの禁止
4. 不正な redirect_uri はエラーページを表示(リダイレクトしない)

クリックジャッキング

認可画面を iframe に埋め込んで不正な認可を誘導する攻撃。

攻撃シナリオ:

1. 攻撃者のページに認可画面を iframe で埋め込み
2. 透明な iframe を重ねて配置
3. ユーザーが「ゲームをプレイ」などのボタンをクリック
4. 実際には認可を許可するボタンをクリック

┌─────────────────────────────────┐
│ 攻撃者のページ │
│ ┌───────────────────────────┐ │
│ │ 透明な iframe(認可画面) │ │
│ │ [許可する] │ │
│ └───────────────────────────┘ │
│ ↑ │
│ [ゲームスタート] ← ユーザーはこれをクリックしたつもり
└─────────────────────────────────┘

対策:

1. X-Frame-Options ヘッダー
X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN

2. Content-Security-Policy
Content-Security-Policy: frame-ancestors 'none'

3. JavaScript によるフレームバスティング
if (self !== top) {
top.location = self.location;
}

フィッシング

偽の認可画面でユーザーの認証情報を盗む攻撃。

攻撃シナリオ:

1. 攻撃者が正規の AS に似た偽サイトを作成
https://auth.examp1e.com('l' を '1' に)

2. ユーザーを偽サイトにリダイレクト
3. ユーザーが認証情報を入力
4. 攻撃者が認証情報を取得

対策:

1. ユーザー教育
- URL を確認する習慣
- ブックマークからアクセス

2. 認可サーバー側
- カスタムブランディング
- ユーザー固有の画像表示

3. パスキー(FIDO2)
- フィッシング耐性のある認証
- オリジンにバインド

第5部: 対策まとめ

必須の対策

対策説明
PKCE認可コード横取り防止
stateCSRF 防止
nonceリプレイ防止(OIDC)
TLS通信の暗号化
redirect_uri 検証完全一致

推奨の対策

対策説明
DPoPトークンバインディング
mTLSクライアント認証とトークンバインディング
PAR認可リクエストの保護
JARM認可レスポンスの保護
RFC 9207 issMix-Up 攻撃防止

運用上の対策

対策説明
短い有効期限漏洩時の影響を限定
トークンローテーション定期的な更新
監査ログ異常検知
レート制限ブルートフォース防止

参考リンク