OAuth2.0におけるstate(CSRF対策)とPKCEの違い
※本記事はOAuth2.0のフローを理解している人向けの記事です。
先日仕事で、とある外部APIのアクセストークン発行までのAPI設計書を書いていました。
そこで、こんな疑問が浮かびました。
「CSRF
って、退会とか送金とか実行によって被害者が直接被害に遭うようなAPIを実行させる攻撃だよな...?なんで認可フローで対策する必要があるんだ...?」
「CSRF
とOAuth PKCE
ってやってること似てね...?これどっちもやる必要ある...?」
...と。
なので今回はOAuth2.0
での二つの働きとその違いについて調べてみました。
個々の詳しい説明は他の素晴らしい記事を参照してください。
結論
それぞれ違う攻撃の対策なのでどっちも必要。
それぞれの説明
フロー
CSRF
1.ランダムな文字列を生成し、サーバのDB、またはクライアントの(一時的な情報のため)セッションなどでstate
として保持。
2. 認可サーバへの認可コードリクエストのリクエストパラメータstate
に、ランダムな文字列を付与し実行。
4. 認可サーバのレスポンスによりクライアントが任意のURLにリダイレクトする。
5. サーバはリダイレクト先のクエリパラメータにあるstate
と、保持していたstate
の値が一致していることで、通信の正当性を確認する。
PKCE
- 以下の条件を満たす文字列を生成し、
code_verifier
としてサーバまたはクライアントに保持。
アルファベット、数字、-、.、_、~から成り、43~128文字
- 事前に選定した
code_challenge_method
でcode_verifier
をハッシュ化。 - 認可サーバへの認可コードリクエストのリクエストパラメータ
code_challenge
に、生成したハッシュを付与し実行。 - 認可サーバは
code_challenge
を保持。 - (認可リクエストのレスポンスはフローに関係ないので飛ばす)
- 認可サーバへのトークン取得リクエストのリクエストパラメータ
code_verifier
に、保持していた同名の文字列を付与し、同様にcode_challenge_method
を付与して実行。 - 認可サーバはハッシュ化に使用した
code_challenge_method
を元に保持するcode_challenge
をデコードし、code_verifier
と一致する文字列が取得できることで、通信の正当性を確認する。
特徴
CSRF
- 認可コードリクエスト実行者と認可コードのレスポンスを受け取った人物が違うことを検知する
- 生成した生の文字列を利用すること。
- 認可コード取得のタイミングで検証すること。
- サーバ側で検証すること。
PKCE
- 認可コードリクエスト実行者とトークン取得リクエスト実行者が違うことを検知する
- 生成した文字列をハッシュ化して利用すること。(しない場合もある)
- トークン生成のタイミングで検証すること。
- 認可サーバ側で検証すること。
弾くことのできる脅威とその攻撃シナリオ
CSRF
弾く攻撃 | 攻撃による被害 |
---|---|
攻撃者のリソース(外部APIを通して利用できる外部のリソース)が、被害者のアプリに紐づく。 | 被害者がアプリにリソースを登録した場合、攻撃者の外部リソースに保存される。 |
想定される攻撃シナリオ
- 攻撃者は自身で認可コードリクエストを実行し、リダイレクトURLのリソース読み込み時点でフローを中断する。
- 認可フロー全体が止まり、攻撃者はリダイレクトURLとどのアプリユーザにも紐づいていない認可コードを取得する。
- 通常の
CSRF
の手口で被害者に取得したリダイレクトURLを実行させ、以降の認可フローを被害者に実行させることで、被害者のアプリと攻撃者のリソースを紐づける。
PKCE
弾く攻撃 | 攻撃による被害 |
---|---|
被害者のリソースが、攻撃者のアプリに紐づく。 | 被害者の外部リソースにある情報が攻撃者に抜き取られる。 |
想定される攻撃シナリオ_ネイティブアプリ
- 認可コードリクエストのレスポンスで遷移するリダイレクトURLによって実行されるカスタムURLスキーム(紐づくネイティブアプリなどをブラウザ画面から実行できるリンク)と同じカスタムURLスキームを設定した攻撃用アプリを被害者のデバイスにインストールしておく。
- 実際にリダイレクトURLがブラウザで実行される時、本来ならば正規のアプリが実行されるが、同じカスタムURLスキームが設定された攻撃用アプリに認可コードが送られてしまう。
--> リダイレクト先はリダイレクト前のセッションを保持するという脆弱さを突いた攻撃。 - 攻撃用アプリを通じて認可コードを横取りした攻撃者は、認可フローを乗っ取ることで被害者のアクセストークンを取得し、被害者のリソースに不正アクセスする。
想定される攻撃シナリオ_webアプリ
前提
: 認可コードを発行してからアクセストークンを取得するまでにラグがある、または認可コードを再利用してアクセストークンが発行できる場合。
- なんらかの方法で認可コードが奪われた場合、攻撃者は認可コードを添付したトークン取得リクエストを実行することでアクセストークンを取得する。
まとめ
CSRF
対策は、攻撃者の認可コード(アクセストークン)と被害者のアプリユーザを紐付けさせないためのもの。
PKCE
は、攻撃者のアプリユーザと被害者の認可コード(アクセストークン)を紐付けさせないためのもの。
PKCE
はCSRF
対策にもなると言っている人もいたりするが、それぞれが別の攻撃の対策になっているため、互いにとって変わることはできない。
Discussion