😈

OAuth 2.0 Device AuthZ Grant +フィッシングのリスクとは

2021/08/24に公開

こんにちは、ritouです。
こんな記事を見かけました。

本投稿では、ここに出てくるRFC8628 OAuth 2.0 Device AuthZ Grantとフィッシングがもたらすリスクにについてざっくり整理しましょう。

OAuth 2.0 Device AuthZ Grantのフロー

仕様を見ろというのはなかなか辛いと思いますが、Device AuthZ Grantについては割とたくさんの記事が出ています。

どんなフローなのか、シーケンスを見てみましょう。

  • (A), (B)で、Clientは自身の識別子やアクセスしたいリソースの範囲などをAuthZ Serverに送信し、ユーザーが許可するためのURLなどを受け取る
  • (C)でClientはQRコードやURL自体を表示するなどしてユーザーをAuthZ Serverに誘導、ユーザーは必要に応じて認証処理をした上でリソースアクセスに対する許可を行う(D)
  • その間、Clientは定期的にトークンを要求する(E)
  • ユーザーが許可したタイミングで各種トークンが返される(F)
  • 後はよしなにリソースアクセス

ってな流れです。

抑えておきたいのは、今回はこのフローのどこかをぶっ壊してどうこうという話ではなく、攻撃者もこの手順を踏んでトークンを取得できれば "それなりに" リソースアクセスできるよね、という部分です。

クライアント認証の有無と、なりすまし

攻撃者がこのフローを手元で再現するためのポイントは、上記シーケンスの(A)(B), (E)(F)のClientとAuthZ Serverの直接通信の部分です。

そもそも、この直接通信が正規のClientのみが行えるのであればリスクは低いでしょう。
仕様を読んでみます。

  The client authentication requirements of Section 3.2.1 of [RFC6749]
   apply to requests on this endpoint, which means that confidential
   clients (those that have established client credentials) authenticate
   in the same manner as when making requests to the token endpoint, and
   public clients provide the "client_id" parameter to identify
   themselves.

RFC6749に準ずるってことは、クライアント認証を利用できるかどうかはClientのタイプに依存します。

  • Confidential Client : ClientID と ClientSecret もしくはそれ以外のクレデンシャルを利用したクライアント認証を利用
  • Public Client : ClientID のみ

となるわけです。
私は個人的によく「安全に実装したいならClient側もデバイス-バックエンドサーバー間でセッションはって大事な処理はサーバー(Confidential Client)でやるしかない」みたいなことを書きますが、そもそもこのフローを利用したいのが

  • ネットワークがあって通信はできる
  • ユーザー入力装置がショボかったりなかったり安全じゃなかったり
  • ユーザーをURLに誘導できる

みたいなところなので、後述しますがリソースアクセスの範囲を適切に絞るなどした上でPublic Clientからの利用を許可する場合が多いでしょう。
その場合、Public ClientのClientIDは秘匿できるようなものではないので、攻撃者が正規のクライアントになりすまして上記の間接通信を行うことは容易であると言えるでしょう。

While investigating the device code flow, Secureworks researchers observed implementations that required only a client ID to generate the user code and device code and then subsequently poll for authentication. This behavior seemed to indicate that a threat actor could use the flow to conduct a phishing attack and impersonate legitimate client applications.

フィッシングとの相性

上記(C)でユーザーが誘導されるURLはAuthZ Server のものです。
正規のフローに従っている以上、アクセスしてしまったURLを確認しても、GoogleやMSのものですし要求されるMFA含めた認証についても正規のものです。

何かしらで表示されたURL、メールやSMSで送られてきたURLにユーザーがアクセスするという流れ自体がフィッシングと非常に近いものです。この部分だけで攻撃者が正規のClientになりすましているかどうかを判断することはなかなか困難でしょう。

ここまでで、攻撃者による直接通信とフィッシングによる誘導が可能であることがわかりました。

アクセス対象のリソース管理、許可

ここから先はAuthZ Serverによる

  • Device AuthZ Grant をどの Client に許可するか
  • Device AuthZ Grant でどのような scope の指定を許可するか
  • 取得したトークンはいつまで利用可能か

と言った仕組みの部分と

  • リソースアクセスを要求しているClientについてユーザーにどこまで説明しているか
  • 要求されているscopeについてユーザーにどこまで説明されているか

というUXの部分によって、最終的にトークンを取得された後に起こりうる被害が変わってくるでしょう。
自分のユーザー識別子とニックネームだけが取れてスマートスピーカーからこんにちはなんとかさんってお喋りさせるぐらいの話と、あのAPIもこのAPIもたたける...ってのはだいぶ違います。

今回の例に出てきた仕組みではその辺りがなかなか緩かったような書き方がされています。

Note that in the request, we did not need to supply any new information. The scope is passed in but is a very limited ”openid” scope. Our response gives us an access_token with user_impersonation, which means full privileges of the user on the resource. No secrets were required either. The lateral movement from Graph API access to Azure API access was fairly straightforward.

まとめ

今回の記事では以下の3点について説明しました。

  • OAuth 2.0 Device AuthZ Grant を Public Client から使わせる場合の話である
    • client_id がわかれば攻撃者はアクセス許可のためのURLを取得したりトークン取得のためのポーリングができたりする
  • メールやSMSなどで送られたURLなども全て正規のものであるため、ユーザー誘導部分でのフィッシング検知は困難
    • AuthZ Serverとしては表示内容なども気にしないといけないが限界はある
  • scope/resource設計により被害が決まる
    • 大きな権限を許可してしまうと大変なことに...

単純に OAuth 2.0 Device AuthZ Grant の仕組みがヤバすぎるというお話ではないものと認識していますが、フィッシングとの相性や何かあったときの被害を想定するリソース設計については意識しておきたいですね。

ではまた。

Discussion