SC Workbook
科目 A-2 · セキュリティ

PKCE による認可コード保護

スマートフォンのネイティブアプリが,OAuth 2.0 の認可コードグラントに PKCE(code_challenge_method は S256)を組み合わせて利用している。攻撃者は,同じカスタム URI スキームを登録した不正アプリによって認可レスポンスの認可コードを横取りし,認可リクエストの内容も観測できた。client_id も攻撃者に知られている。攻撃者がこの認可コードを使ってトークンリクエストを送った結果として,適切なものはどれか。

  1. ア認可コードは有効期限内であれば提示者を問わず有効なので,攻撃者は認可コードと client_id を送るだけでアクセストークンを取得できる。
  2. イ攻撃者は,観測した code_challenge の値を code_verifier としてトークンリクエストに含めれば,アクセストークンを取得できる。
  3. ウ認可サーバは,認可レスポンスが不正アプリに渡った時点でリダイレクト URI の不一致を検出し,その認可コードを無効にする。
  4. エ攻撃者は code_verifier を知らず,code_challenge から求めることもできないので,トークンエンドポイントはエラーを返し,アクセストークンは発行されない。
正解と解説を見る

正解 エ

この問題の基礎知識

  • OAuth 2.0 の認可コードグラントでは,クライアントは認可エンドポイントから認可コードを受け取り,それをトークンエンドポイントでアクセストークンと交換する。
  • ネイティブアプリはクライアントシークレットを安全に保持できず,カスタム URI スキームは他のアプリも登録できるので,認可コードを横取りされ得る。
  • PKCE では,クライアントが乱数の code_verifier を生成し,その変換値の code_challenge を認可リクエストに,code_verifier をトークンリクエストに含める。認可サーバは両者が対応するかを確認する。
  • S256 では code_verifier の SHA-256 ハッシュ値を base64url 符号化して code_challenge とするので,ハッシュ関数の一方向性により code_challenge から code_verifier は求められない。plain では両者が同じ値になる。
ア認可コードは有効期限内であれば提示者を問わず有効なので,攻撃者は認可コードと client_id を送るだけでアクセストークンを取得できる。

PKCE を用いなければこの攻撃は成立し得るが,PKCE を用いた場合,認可コードは,認可リクエストの code_challenge に対応する code_verifier を併せて提示しなければトークンと交換できない。

イ攻撃者は,観測した code_challenge の値を code_verifier としてトークンリクエストに含めれば,アクセストークンを取得できる。

S256 では,トークンエンドポイントが受け取った code_verifier の SHA-256 ハッシュ値を base64url 符号化して code_challenge と比較する。code_challenge をそのまま送っても一致しない。両者が同じ値になるのは plain の場合である。

ウ認可サーバは,認可レスポンスが不正アプリに渡った時点でリダイレクト URI の不一致を検出し,その認可コードを無効にする。

不正アプリは正規のアプリと同じカスタム URI スキームを登録しており,認可サーバから見たリダイレクト URI は正規のものと変わらない。端末内でどのアプリが応答を受け取ったかを,認可サーバは知ることができない。

エ攻撃者は code_verifier を知らず,code_challenge から求めることもできないので,トークンエンドポイントはエラーを返し,アクセストークンは発行されない。正解

code_verifier は正規のアプリだけが保持し,認可リクエストにはそのハッシュ値から作った code_challenge だけが含まれる。ハッシュ値から code_verifier は求められないので,横取りした認可コードはトークンと交換できない。

検証用の出典出典照合済み
RFC 7636 Proof Key for Code Exchange by OAuth Public Clients / RFC 6749 The OAuth 2.0 Authorization Framework
照合の根拠(4 件)
  • ウ(誤り): 不正アプリは同じカスタムスキームのハンドラとして登録できるので,認可サーバから見たリダイレクト URI は正規のものと変わらない
    Note that it is possible for a malicious app to register itself as a handler for the custom scheme in addition to the legitimate OAuth 2.0 app.
    RFC 7636 · Section 1(新しいタブで開きます)
  • エ(正解)・ア(誤り): code_verifier を持たない攻撃者は横取りした認可コードをトークンと交換できない
    An attacker who intercepts the authorization code at (B) is unable to redeem it for an access token, as they are not in possession of the "code_verifier" secret.
    RFC 7636 · Section 1.1(新しいタブで開きます)
  • イ(誤り): S256 では受け取った code_verifier のハッシュ値を code_challenge と比較するので,code_challenge をそのまま送っても一致しない(直接比較は plain の場合)
    If the "code_challenge_method" from Section 4.3 was "S256", the received "code_verifier" is hashed by SHA-256, base64url-encoded, and then compared to the "code_challenge", i.e.:
    RFC 7636 · Section 4.6(新しいタブで開きます)
  • エ(正解): 一致しなければトークンエンドポイントはエラー(invalid_grant)を返す
    If the values are not equal, an error response indicating "invalid_grant" as described in Section 5.2 of [RFC6749] MUST be returned.
    RFC 7636 · Section 4.6(新しいタブで開きます)

問題文では認可リクエストも観測されている(RFC 7636 1 章の前提 4b)が,S256 なので観測できるのは code_challenge だけで,SHA-256 の一方向性により code_verifier は求められない。

問題 ID A2-SEC-0007 · AI 作成のオリジナル問題 · 正解と各選択肢の根拠を出典の原文で確認しています。 照合日 2026-11-08

非公式の学習用アプリです(IPA とは関係ありません)。問題はすべて AI が作成したオリジナルで、誤りを含む場合があります。