認可コードは「金塊」である:リダイレクトURIの厳密検証が守るべき境界線
OAuth 2.0やOpenID Connectのフローにおいて、認可コード(Authorization Code)は単なる一時的な文字列ではない。それはユーザーのアイデンティティそのものであり、攻撃者にとっては奪取した瞬間に「なりすまし」という名の富をもたらす金塊だ。
多くの開発者がリダイレクトURIの検証を「単なる文字列比較」と誤解している。しかし、現場で遭遇するインシデントの多くは、この「甘い検証」が引き起こすオープンリダイレクトの連鎖によって発生している。今日は、プロトコルレベルの仕様と、攻撃者がパケットを捏造してまで狙う「認可コード流出」のメカニズムを解剖しよう。
—
1. なぜ「部分一致」が破滅を招くのか
RFC 6749の仕様を読み解けば、「リダイレクトURIは厳密にマッチングすべきである」と明記されている。しかし、開発現場では利便性を優先して、サブドメインのワイルドカード指定や正規表現による曖昧なマッチングを許可してしまうケースが後を絶たない。
攻撃者は何を狙っているか?それは、認可サーバーが信頼しているドメイン内に存在する「オープンリダイレクト脆弱性」だ。
- 攻撃シナリオ:
1. 攻撃者は、ターゲットサイト(trusted.example.com)上のオープンリダイレクトエンドポイントを見つける。
2. 認可リクエストの redirect_uri パラメータに、https://trusted.example.com/redirect?url=https://attacker.com を注入する。
3. 認可サーバーが「trusted.example.com で始まっているからOK」と判定し、認可コードをそのURLへ送出する。
4. ユーザーのブラウザは trusted.example.com にアクセスし、即座にクエリパラメータに含まれた悪意あるサイトへ、認可コードを付与したままリダイレクトする。
この時点で、認可コードは攻撃者のサーバーのログに綺麗に記録される。これが「認可コード流出」の最短ルートだ。
—
2. 厳密なホワイトリスト検証のアーキテクチャ
防御の鉄則は、「ホワイトリストによる完全一致(Exact Match)」のみを許容することだ。設定値の管理には、データベースの動的な書き換えを避け、デプロイ時に読み込まれる静的なコンフィグファイルや、厳格なバリデーションロジックを持つ認可サーバーのコアエンジンを利用すべきである。
以下は、Go言語による検証ロジックの概念実装だ。
// 安全な検証ロジックの例
func validateRedirectURI(requestedURI string, allowedURIs []string) bool {
// 1. 正規化(Normalization)
// URLのエンコーディング不一致によるバイパスを防ぐため、一度パースして再構築する
u, err := url.Parse(requestedURI)
if err != nil {
return false
}
// 2. 完全一致チェック
// 部分一致やワイルドカードは一切認めない
normalizedRequested := u.String()
for _, allowed := range allowedURIs {
if normalizedRequested == allowed {
return true
}
}
// 3. ログ記録
// 不正なURIが送られてきた場合、即座にSIEM等へアラートを飛ばす
log.Printf(“Security Alert: Invalid redirect URI attempt: %s”, normalizedRequested)
return false
}
—
3. 次世代の防衛:PKCEと境界防衛の融合
「リダイレクトURIの検証」だけで安心するのはまだ早い。今の時代、認可コードの奪取は防げないという前提で設計する「ゼロトラスト認可」が必要だ。
PKCE(Proof Key for Code Exchange)の強制
PKCEは、本来はモバイルアプリ向けの仕様だったが、今やWebアプリの標準である。code_verifier と code_challenge を組み合わせることで、たとえ攻撃者が認可コードを盗み出しても、ペアとなる検証鍵がなければアクセストークンを交換できないようにする。これは、リダイレクトURI検証の「最後の守護神」だ。
生成AIによるプロンプトインジェクションへの備え
最近では、認可サーバーのUIを生成AIでカスタマイズしているケースも見かけるが、そこには「認可プロンプトの改ざん」という新たなリスクがある。認可サーバーが出力する HTML やリダイレクト先を生成AIが決定する場合、その出力に対して「認可境界を越えない」ためのガードレイル(入力および出力のフィルタリング層)を、バイナリレベルで制御するアーキテクチャを導入すべきだ。
—
チーフホワイトハッカーからの提言
我々の世界では「動くこと」と「安全であること」は同義ではない。むしろ、機能が正常に動いている時ほど、裏側で何が起きているかを疑うべきだ。
リダイレクトURIの検証を怠ることは、銀行の金庫の鍵を「とりあえず開けばいい」と調整しているのと同じだ。今すぐ、あなたの認可サーバーのログを叩き、許可されていないURIへのアクセスが試行されていないか確認してほしい。攻撃者は常に、あなたのコードの最も脆い「柔軟性」を狙っている。
セキュリティとは、技術の積み重ねであると同時に、こうした「細部への執着」の積み重ねでもある。明日からの開発で、リダイレクトURIのバリデーションを厳格化し、ログを監視する。その小さな一歩が、数百万ユーザーのアイデンティティを守る盾となるのだ。
コメント