PKCE で防げる「認可コード横取り攻撃」とはどのような攻撃か

PKCE で防げる「認可コード横取り攻撃」とはどのような攻撃か

「どうすればそれを実装できるか?」は理解に易くても、
「何故そういう仕組みになったのか?」といったところに焦点を当てた丁寧な解説って、あまりなかったりしますよね。
PKCE-1.png

自分自身、残念ながら腑に落としきれないまま実装することが少なくなかったり、
世の中に出回っているサービスでも、
仕様の意味をきちんと理解されていないのかパラメータが本来の目的で使われておらず隙が発生してしまっているものが存在したり・・・。

ということで、
PKCE について、自分が知っている範囲でメモ残しておこうと思います。

本来あるべきを考える

PKCEとは?

PKCEは、OAuth 2.0 の拡張仕様で、
Public Client が被り得る「認可コード横取り攻撃」を防ぐためのものです。
ぴくしーと読みます。OAuthのセキュリティを守る妖精さん:dizzy::dizzy:

仕様はこれ:point_down::point_down:

Proof Key for Code Exchange by OAuth Public Clients
https://tools.ietf.org/html/rfc7636

Public Client は Implicit Flowでは?

:question: Public Client ってそもそも Implicit Flowでは:question:
・・・ごもっともです:sweat_smile:

でも、なんで Public Client は Implicit Flow を使うんでしょう:question::question:

Authorization Code Flow でも ダメなわけではないと思われます。
ただ、Public Client は client_secret を安全に保持できる機密性を有しておらず、
redirect_uri が事前登録されているものであるか否かしかClient検証のポイントがありません。

ということで、Tokenエンドポイントでの codetoken を省略し、
redirect_uri に直接 token を返却して通信回数を減らしているのがImplicit Flowです。

「通信回数を減らす」が大きな目的であって、
「セキュリティを向上させている」わけではないです。
(クエリではなくフラグメントで返すとかImplicitではRefreshToken発行しないとかの考慮はあります)

なので、Client認証がきちんと行えて、
Authorization Code Flowで、token取得できるに越したことないよね、
ということです。

Public Client で Authorization Code Flow

では、Public Client で Authorization Code Flow を行った場合どうなるかを見てみましょう。

PKCE-2.png
一見、何も問題ないように見えますが、どこに攻撃する隙があるのか、見てみましょう。

危ない!認可コード横取り攻撃!

認可コード横取り攻撃とは?

ようやく出てきました。
「認可コード横取り攻撃」です。

先に記したPublic Clientで通常のAuthorization Code Flow を行った際のフローでは、4' で Browser → app に遷移する際に、隙があります。

攻撃者が、正規の「app」と同じカスタムスキーム app:// で起動する「Malicious app」を作成してユーザの端末に何らかの形でインストールさせることに成功していた場合、下記の通り「認可コード横取り攻撃」のフローが成立してしまいます:bangbang::bangbang:

PKCE-3.png

4' で Browser → app に遷移する際に、カスタムスキームを悪用して遷移先を横取りし、以降「Malicious app」が 正規の「app」になりすましてユーザの大事な Resource を不正に入手してしまいます。

PKCEではどのようにして防いでいるか?

PKCEでは、code_verifierの値をcode_challenge_methodで指定した方法で計算して得られた値code_challengeが、appで計算したものと、Serverで計算したものと一致することを確認することで、リクエスト送付元の検証を行っています。

PKCE-4.png

appからは、「2. AuthoZ Request」の際にcode_challenge_methodcode_challengeを送付し、
「5. Token Request」の際にcode_verifierの値を送付します。
Server側では「2. AuthoZ Request」で受け取った値をcodeと紐付けて保存しておき、「5. Token Request」で受け取ったcode_verifierと「2. AuthoZ Request」で受け取ったcode_challenge_methodで算出した値が、「2. AuthoZ Request」で受け取ったcode_challengeと一致するか確認することで、「2. AuthoZ Request」の送付元と「5. Token Request」の送付元が同じであることを検証します。

PKCE-5.png

「Malicious app」が「認可コード横取り攻撃」をしようとしても、Token Request送付時に、code_verifierの値が分からず送れない、あるいは出鱈目な値を送っても、Server側でそのようなClientを弾けますね。

PKCE-6.png

PKCEを利用しても防げない攻撃

「なりすまし」

PKCEを利用したら、Client認証ができるようになる:exclamation:と言うわけではありません。
あくまで「認可コードを要求したClient」と「Tokenを要求しているClient」が同一であることが検証されるのみです。

なので、「認可コードを要求」からなりすましてしまう「Malicious app 2」をユーザが利用してしまった場合は、Tokenが発行され、ユーザの大事な Resource が不正に入手されてしまいます。

PKCE-7.png

ただこの場合、「Malicious app 2」を立ち上げたにもかかわらず、同意画面では正規の「app」に対する同意が確認されるという矛盾が発生します。

「認可コード横取り攻撃」では、正規の「app」を立ち上げて、同意画面でも正規の「app」に対する同意が確認されるにもかかわらず、「Malicious app」にTokenを発行してしまうため、ユーザから見て気付ける余地がなく防ぎようがありません。

「なりすまし」については、発生してしまう可能性はありますが、「Malicious app 2」を立ち上げているにもかかわらず、同意画面では正規の「app」に対する同意画面が表示されるため、ユーザがおかしいことに気付ける可能性が高いと思われます。

おわりに

PKCEのより詳しい情報は下記などを参照ください。

RFC7636として発行されたOAuth PKCEとは
http://d.hatena.ne.jp/ritou/20151018/1445181974

OAuth 2.0 and PKCE
https://blog.pedrofelix.org/2016/02/15/oauth-2-0-and-pkce/

PKCE: 認可コード横取り攻撃対策のために OAuth サーバーとクライアントが実装すべきこと
https://qiita.com/TakahikoKawasaki/items/00f333c72ed96c4da659

Public Clientで動かす際には、PKCE対応必須で実装しておくべきですね:blush::blush:

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.