『OAuth・OIDCへの攻撃と対策を整理して理解できる本(リダイレクトへの攻撃編)』を読んだ

目的

前作・前々作を読んで理解しましたが、攻撃を仕掛ける側はどうやって攻撃をしてくるのか、それの対策方法を知りたかったからです。

techbookfest.org

以下は、前作・前々作の記事です。

blog.ryskit.com

blog.ryskit.com

感想

OAuthやOIDCのおさらいは書かれているものの、理解ある前提ではあると思うので、事前に前作・前々作を読んでから読むのが良いかなと思います。

techbookfest.org

techbookfest.org

この本では、OAuth/OIDCへの5種類の攻撃方法の説明とその対策がシーケンス図とともに分かりやすく書かれています。

だいたいはOAuth/OIDCを使う側だと思うので、認可サーバを実装する機会はあまりないかと思いますが、クライアントやリライングパーティ側で特定の値の検証することで攻撃への対策ができるものもあります。

そういった対策をこの本を読んで知っておくことで、「ライブラリやフレームワークを選定する場合」や「自ら実装する場合」に活きてくるのかなと思いました。

第7章の全体整理では、OAuth/OIDCのどのグラント/フローの場合にどのような攻撃がされるのか、その対策は何なのか、第6章までで説明された内容がフォーマットに沿って整理されているため、時間が経って詳細を忘れた場合でも思い出すのに役立ちそうです。

読書メモ

第1章 OAuth・OIDCのおさらい

  • OAuth Danceとは
    • 認可コードフロー、インプリシットフローではクライアント・認可サーバ間で何度も情報のやりとりが行われるが、その様子を指す
  • OAuth Danceの中で認可レスポンスが狙われる理由は3点
    • 認可コード、アクセストークン、IDトークンなどの情報がURIの中に含まれている
    • 認可サーバ、クライアント間の情報のやり取りの間にブラウザのリダイレクトを介している
    • 認可サーバ・IDプロバイダによるリソースオーナー(エンドユーザー)の認証・同意処理が完了済み
  • 上記のやりとりへの攻撃として5種類の攻撃がある
    • CSRF
    • リプレイスアタック
    • コードインジェクション
    • トークンインジェクション
    • 認可コード横取り攻撃

第2章 CSRF

  • 認可サーバーでは state に対して何の検証も行わない。state の検証を行うのはアプリであることに注意
  • state を使うことで CSRF を防ぐことができる
  • state により 認証リクエストのセッションと認証レスポンスのセッションが同一であることを検証できる
  • OAuthは仕様でstateの利用は任意になっているため、ライブラリやフレームワークを利用する際は事前にstateの検証が正しく行われるかチェックが必要
  • セッションごとにstateを生成しなければならない
  • 推測困難なランダムな文字列を state として使う
  • 認可レスポンスのセッションと state の紐付けを確認する
  • state が含まれていない認可レスポンスはエラーで返す
  • OAuth 2.0 Security Best Current Practice

第3章 リプレイス攻撃

  • 第三者のIDトークンを攻撃者自身の管理下にあるアプリに適用
  • 攻撃対象のフロー
    • インプリシットフロー
    • ハイブリットフロー
  • nonce - number used once
  • リプレイス攻撃を可能にしてしまう原因は、同じIDトークンを他のデバイスのアプリ上で利用できてしまうこと
  • IDトークンの検証完了後、nonce を無効化する

第4章 認可コード横取り攻撃

  • 同じデバイスにインストールされた「同じカスタムスキームを持つアプリ」に認可コードを奪われる。結果、アクセストークンを取得される
  • 対象は、OAuth, OIDC
  • 攻撃対象は、認可コードフロー、ハイブリッドフロー(response_typeにcodeを含むもの)
  • 攻撃を可能にしているポイントが同じカスタムスキームであること
  • PKCE
    • code_verifier
      • 長さ43文字、最大128文字までの間の[A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~" / からなるランダム文字列
    • code_challenge
      • code_verifierに対して code_challenge_method の計算をほどこして算出された値
    • code_challenge_method
      • plain
        • code_challenge = code_verifier
      • S256
        • code_challenge = BASE64URL-ENCODE( SHA256 (ASCII( code_verifier ) ) )
  • 認可サーバで、code_verifierの検証が行われる

第5章 トークンインジェクション

  • 第三者の有効なアクセストークンを攻撃者自身の管理下にあるアプリに適用
  • 攻撃対象は、OAuth、OIDC
  • OAuthには対策がない(独自対応しているサービスはある)
  • at_hash <- access token hash?
    • IDトークンに含まれるクレームの1つ
  • IDトークンには2つの役割がある
    • 認証アサーションとしての役割
    • デタッチ署名としての役割
  • 認証レスポンスのアクセストークンの情報を、ペイロードに含めることで、アクセストークンの署名としても機能する
  • ペイロードには「IDトークンの署名と同じハッシュアルゴリズムでアクセストークンのハッシュ値を算出し、その左半分をBase64URLエンコードした文字列」を at_hashの値に入れる
  • 取得したアクセストークンに対して、上記で算出したat_hashの値とIDトークンのペイロードに埋め込まれたat_hashの値を比較することで入れ替えに気づくことができる
  • インプリシットグラントは使わず、認可コード + PKCE
  • フラグメントはリダイレクト時にその情報がサーバに送られないため、漏洩のリスクが下がる
  • コラム: トークンはどこからもれるのか?が面白い p.66

第6章 コードインジェクション

  • 第三者の未使用の認可コードを攻撃者自身の管理下にあるアプリに適用
  • 攻撃対象は、OAuth、OIDC
  • PKCE・nonce・c_hash(code hash?)による対策が書かれている
  • OAuthの仕様では認可コードは有効期限が短く、一度しか利用できないため、利用されていない許可コードを取得した上で、短い有効期限内に攻撃を完了する必要がある
  • コードインジェクションを防ぐために、アプリは「」セッションとcode_verifierの紐付け」を管理し、認可サーバは「code_challengeと認可コード(code)の紐付け」を管理する必要がある
  • コードインジェクションを防ぐために、アプリはセッションとnonceの紐付けを管理し、IDプロバイダはnonceと認可コード(code)の紐付けを管理する必要がある
  • c_hashが利用できるのは、response_typeの値にid_tokenとcodeの両方が含まれるハイブリッドフロー
  • c_hashは、「IDトークンの署名と同じハッシュアルゴリズムで認可コードのハッシュ値を算出市、その左半分をBase64URLエンコードした文字列」
    • 認証レスポンスで取得した認可コードに対して、上記と同じ演算を行い、同じく認証レスポンスで取得したIDトークンのc_hashの値を比較することで認可コードの入れ替えに気づくことができる

第7章 全体整理

  • 認可フローやクライアントの種別に応じて、攻撃の種別や対策方法がまとめられている
  • ハイブリットフローでのパラメータ共有について p.106