「単なるOAUTH 2.0を認証に使うと、車が通れるほどのどでかいセキュリティー・ホールができる」について

こんにちは、サイオステクノロジー 武井です。

※本記事の英語版はこちら(Click here to read in English)

今回は、OAuthを認証に利用することの危うさについて書きたいと思います。参考にさせていただきましたのは以下の記事になります。

https://www.thread-safe.com/2012/01/problem-with-oauth-for-authentication.html

この記事では、OAuth2.0のImplicit Flowを使って認証を行った場合、悪意のあるユーザーが、簡単に他の誰かになりすますことができてしまうということが書いてあります。

今回、これを私なりにわかりやすく解説を試みてみたいと思います。

OAuth認証とは?

本来、OAuthは認証につかうプロトコルではありません。APIなどの認可(このユーザーに対しては、ユーザー情報を読み取るためのAPIしか使えませんよー的な制限を設けることです)に使うプロトコルです。この場合は、OpenID Connect(詳細は、多分わかりやすいOpenID Connect参照)が適切なのですが、ある手法を使うと、OAuthを認証にも使うことができてしまいます。本章では、このことについて、図を交えながら説明します。

まず、今回の説明の中で登場する人物やサービスをご紹介致します。

Screen Shot 2019-02-25 at 10.27.50 SNS1・・・OAuth認証を実現するために、SNS2からユーザープロフィール情報取得APIの認可を受ける側です。
Screen Shot 2019-02-25 at 10.27.56 SNS2・・・OAuth認証により、Aさんに認証のサービスを提供し、SNS1にユーザープロフィール情報取得APIの使用許可(認可)を提供する側です。
Screen Shot 2019-02-25 at 10.27.41 Aさん・・・SNS1のサービスの利用者です。今回、SNS1を利用するにあたり、SNS2のID、パスワードで認証します。
Screen Shot 2019-02-25 at 10.28.02 SNS1のシステム管理者・・・SNS1のシステム管理者です。

 

これより、OAuthの認証の仕組みを説明します。SNS2はImplicit Flowを使っているものとします。まずSNS1を運営するシステム管理者は、SNS2に対して、OAuthで接続させてくださいみたいな事前の申請をします。これは、SNS2のサービスに申請専用の画面が用意されていることが多いです。その申請フォームに必要な項目を入力します。そのときに必ず、SNS2に対して行いたい作業(閲覧や投稿)を申請します。この場合は、アクセスしてきたユーザーのプロファイル情報(ユーザー情報や名前など)を操作できる権限を申請します。

Screen Shot 2019-02-25 at 10.40.49

 

申請が終わると、SNS2は「クライアントID」「クライアントシークレット」をSNS1システム管理者に発行します。またSNS1から申請があった作業(投稿や閲覧、以下利用サービスと呼びます)を独自の文字列に変換します。SNS2、SNS1は、そのクライアントID、クライアントシークレット、利用サービスを自身のデータベースに保存します。ここまででSNS1システム管理者の仕事は終わりです。この作業はOAuth利用時にシステム管理者が最初の一度だけ行えばよい作業です。

Screen Shot 2019-02-25 at 11.01.15

 

Aさんは、SNS1にアクセスします。

Screen Shot 2019-02-25 at 11.06.22

 

SNS1は、SNS1のログイン画面(Authorization Endpoint)へAさんをリダイレクトします。すると、SNS2のログイン画面が出てくるので、AさんはSNS2にログインするためのIDとパスワードを入力します。

Screen Shot 2019-02-25 at 12.44.27

 

ログインすると、SNS2は、SNS1と連携してもよいかどうかの確認画面を表示します。

Screen Shot 2019-02-25 at 11.13.48

 

Implicit Flowですので、事前にSNS2側でシステム管理者が登録したコールバックURL(https://sns1.example.com/cb.php)のハッシュフラグメントとして、アクセストークンが付与され、Aさんに経由で、SNS1にリダイレクトされます。SNS1はハッシュフラグメントを解析して、アクセストークンを取り出して、SNS1のデータストアに格納します。

Screen Shot 2019-02-25 at 11.33.10

 

SNS1は取得したアクセストークンを使って、SNS2のプロファイルAPIにアクセスして、AさんのIDを取得します。

Screen Shot 2019-02-25 at 11.42.13

 

SNS1は、プロファイルAPIのレスポンスにAさんのIDが含まれていることから、SNS1にアクセスしてきたユーザーはAさんと判断し、Aさんの情報を画面に表示します。これがOAuth認証です。一見すると、なんの問題もないように見えますが、これは、SNS1を含む全てのサイトが「いいサイト」だった場合です。

Screen Shot 2019-02-25 at 11.55.51

 

車が通れるほどのドデカイセキュリティホールができてしまう場合

本章では、OAuthを認証に使った場合に、どのようなセキュリティリスクがあるかをご説明します。ここで新たな登場人物をご紹介致します。

Screen Shot 2019-02-25 at 12.16.16 悪SNS・・・ユーザーAさんの情報を不正に取得し、Aさんになりすますことを企む悪い業者が運営する悪いSNSです。
Screen Shot 2019-02-25 at 12.14.47 悪SNSシステム管理者・・・悪SNSのシステム管理者です。

 

では、悪SNSが、いかにして、Aさんになりすますかをご説明していきたいと思います。

SNS1のときと同様、まず悪SNSを運営するシステム管理者は、SNS2に対して、OAuthで接続させてくださいみたいな事前の申請をします。アクセスしてきたユーザーのプロファイル情報(ユーザー情報や名前など)を操作できる権限を申請します。

Screen Shot 2019-02-25 at 12.20.40

 

申請が終わると、SNS2は「クライアントID」「クライアントシークレット」を悪システム管理者に発行します。これもSNS1のときと同様ですね。

Screen Shot 2019-02-25 at 12.26.22

 

Aさんは、悪SNSにアクセスします。しかし、Aさんは悪SNSが、悪意のあるSNSであり、Aさんになりますことを企んでいるトンデモ野郎であることを知りません。

Screen Shot 2019-02-25 at 12.29.51

 

悪SNSは、SNS1のログイン画面(Authorization Endpoint)へAさんをリダイレクトします。すると、SNS2のログイン画面が出てくるので、AさんはSNS2にログインするためのIDとパスワードを入力します。

Screen Shot 2019-02-25 at 12.46.02

 

Implicit Flowですので、事前にSNS2側でシステム管理者が登録したコールバックURL(https://sns1.example.com/cb.php)のハッシュフラグメントとして、アクセストークンが付与され、Aさんに経由で、悪SNSにリダイレクトされます。悪SNSはハッシュフラグメントを解析して、アクセストークンを取り出して、悪SNSのデータストアに格納します。

Screen Shot 2019-02-25 at 12.55.12

 

悪SNSは取得したアクセストークンを使って、SNS2のプロファイルAPIにアクセスして、AさんのIDを取得します。

Screen Shot 2019-02-25 at 12.57.06

 

悪SNSは、プロファイルAPIのレスポンスにAさんのIDが含まれていることから、悪SNSにアクセスしてきたユーザーはAさんと判断し、Aさんの情報を画面に表示します。

Screen Shot 2019-02-25 at 12.59.49

 

これまでの過程で、悪SNSのシステム管理者はAさんのアクセストークンを取得しました。これより、悪SNSのシステム管理者は、Aさんのアクセストークンを悪用して、SNS1のサービスにてAさんになりすまします。

悪SNSシステム管理者は、SNS1にアクセスします。

Screen Shot 2019-02-25 at 13.28.48

 

SNS1は、SNS1のログイン画面(Authorization Endpoint)へ悪SNSシステム管理者をリダイレクトします。すると、SNS2のログイン画面が出てくるので、悪SNSシステム管理者はSNS2にログインするためのIDとパスワードを入力します。

Screen Shot 2019-02-25 at 13.30.25

 

ログインすると、SNS2は、SNS1と連携してもよいかどうかの確認画面を表示します。

Screen Shot 2019-02-25 at 13.32.38

 

Implicit Flowですので、事前にSNS2側でシステム管理者が登録したコールバックURL(https://sns1.example.com/cb.php)のハッシュフラグメントとして、アクセストークンが付与され、悪システム管理者経由で、SNS1にリダイレクトされます。しかし、ここがキモなのですが、悪SNSシステム管理者は、リダイレクトURLを書き換えて、つまり、悪SNSシステム管理者のブラウザ自身へのHTTPレスポンスに含まれるLocationヘッダに記載されたURLを書き換えて、ハッシュフラグメントの部分を、先程不正に取得したAさんのアクセストークンに置き換えます。

Screen Shot 2019-02-25 at 13.37.21

 

すると、SNS1は悪SNSシステム管理者を経由してリダイレクトされてきたアクセストークンを受け取り、SNS2に対してそのアクセストークンでプロファイルAPIを発行します。すると、、、

Screen Shot 2019-02-25 at 13.44.53

 

なんと、Aさんのプロフィール情報が返ってきてしまいました。これで、Aさんになりすましてログインできることになってしまいます。

Screen Shot 2019-02-25 at 13.48.49

対策について

対策は主に2つあると思います。

一つは、SNS1はそのアクセストークンの発行元を検証することです。今回の大きな原因は、SNS1が、アクセストークンをのべつ幕なしにすべて受け入れていることにあります。SNS1がアクセストークンを発行する際、このアクセストークンがどのクライアント宛に発行されたものかを記録し、アクセストークの検証をする際、合わせてその発行元も確認することです。例えば、SNS1はSNS2にアクセストークンを発行する際、このアクセストークンがSNS1宛に発行されたものだという情報をどこかに持っておきます。データベースでもファイルでもなんでも構いません。そして、SNS1がアクセストークンをSNS2に送ってきた場合、SNS1から発行されたものでなければ、それをSNS1側で拒否をします。そうすれば、この攻撃を防ぐことができます。

もう一つは、OpenID Connectを導入することです。これが一番、確実な対策かと思います。もともと、OAuthは認証のために使うプロトコルではありませんし。

 

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

8人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です