2016年7月24日日曜日

攻略! #PokemonGo のログインと OpenID Connect

こんにちは、富士榮です。

世の中 Pokemon Go / ポケモン Go 一色ですが、いかがお過ごしでしょうか?

あいにく私の住んでいる地域は過疎化が進んでおり、ポケモンがほとんどおりません・・・・



おかげで全然レベルが上がらないので、ジムなどには無縁な平和な生活を営んでいるわけなんですが、果たして Pokemon Go のログオンは平和なのか?という ID 厨なら必ず抱く疑問を解消すべく、家族で地元の夏祭りに参加している横で解析をしてみました。

公開当初はフルアクセスを要求するアプリだったので、プチ炎上したりしましたが現状は解消されたということなので、パケットキャプチャしてみます。

 参考)ポケモン Go がフルアクセスを要求していた件。



では早速、Pokemon Go へのログインの仕組みを見ていきましょう。
Pokemon Go ではいわゆるローカルアカウント(Pokemon Trainer Club)と Google アカウントを使ってログオンする2つの仕組みが用意されています。

色々な Web サイトを見ると、専用の Google アカウントを作るべきである、というような記事を見かけたりしますが、根拠として先のとおり、すべて権限を要求するから、という理由が挙げられています。

 参考)ポケモン Go をプレイするなら専用の Google アカウントを作るべき


まぁ、公式発表によると権限周りは修正されたということなのですが、実際にどのような権限が要求されているのか、ログオン~ユーザ登録のシーケンスにおいて何が起きているのかを見ておきたい、ということで解析してみましょう。

◆準備

基本的に通信をキャプチャすることになるので、プロキシを用意して HTTP/HTTPS の通信を覗いてみたいと思います。今回はiOS版を使ったので、PC にインストールした Fiddler をプロキシとして使うように iOS の Wifi 設定を行います。

今回は、PC で Fiddler を立ち上げ、リモートクライアント向けのプロキシとして動作するように設定を行いました。

Tools より Fiddler Options を開き、Connections タブへ以下の通り設定を行います。
- Fiddler Listen Port : 8888(デフォルト)
- Allow remote computers to connect : ON

これで PC にインストールした Fiddler がプロキシとして動作するようになります。
ちなみに、 Windows Firewall が邪魔をするので、外部からの 8888 への通信を許可するように設定をしておく必要があります。

また、HTTPS 通信を復号するためには、Fiddler の使う証明書を iOS が信頼するように構成する必要があるので、 Fiddler で証明書をエクスポートし、iOS 側へ送信、インポートしておく必要があります。(細かい手順は割愛します)


次は、iOS 側の設定で、Fiddler をプロキシとして使うようにしまう。
設定から Wifi を開いてプロキシサーバのアドレスとポートに Fiddler を動かしている PC のアドレスと先のポート番号を指定します。




これで準備は完了です。

早速、Pokemon Go をインストールしてサインアップしてみます。

◆Google アカウントでサインアップした場合の要求スコープは?

Pokemon Go を起動し Google アカウントでサインアップを選択します。


ここで、Googleを選択した時の通信キャプチャを見ると、以下のようなリクエストが飛んでいます。


GET https://accounts.google.com/o/oauth2/auth
?client_id=84....snip......apps.googleusercontent.com
&redirect_uri=urn:ietf:wg:oauth:2.0:oob
&response_type=code
&scope=openid email https://www.googleapis.com/auth/userinfo.email HTTP/1.1

注目すべきは scope パラメータです。OpenID Connect のリクエストなので当然 openid は含まれるとして、email および https://www.googleapis.com/auth/userinfo.email が含まれています。
Google の OpenID Connect 関係のドキュメントを見ると、email と は同じスコープで、メールアドレスの表示だけを要求していることがわかります。

画面上に表示されるとおりですね。

ここで、許可をクリックすると token エンドポイントへ認可コードが POST される普通の OpenID Connect の流れが続きます。

POST https://accounts.google.com/o/oauth2/token HTTP/1.1

ボディ
client_id=84...snip...alem.apps.googleusercontent.com
&client_secret=NCjF1...snip....uL7
&code=4/D7vS...snip....i7h1Q_njLCM
&grant_type=authorization_code
&redirect_uri=urn:ietf:wg:oauth:2.0:oob
&scope=openid email https://www.googleapis.com/auth/userinfo.email


結果、access_tokenやid_tokenが返ってきます。

{
  "access_token" : "ya29.Ci8pAxbo....snip...FA",
  "token_type" : "Bearer",
  "expires_in" : 3600,
  "id_token" : "eyJhbGciOiJSUzI1....snip.....XsXHNwQ",
  "refresh_token" : "1/lCAJhP...snip....TM"
}


もちろん id_token の中身を jwt.io などで覗くといい感じで Google アカウントの情報が出てきます。




さて、問題はこの後です。
email をスコープとして access_token を要求しているので、必要以上の情報を Google が提供することはありませんが、どのような要求が Pokemon Go から実施されているのでしょうか?

結論、サインアッププロセスの中で access_token が使われることはなく、 id_token の中のメールアドレスだけを使っているように見えます。

続くリクエストは運営元の Nianteclabs.com への POST なのですが、所謂 RESTful API 的に JSON などがやり取りされるわけではなく、バイナリデータが飛び交うのでこれ以上の解析はしませんが、見えている範囲では、 id_token がそのまま POST されているようです。

POST https://pgorelease.nianticlabs.com/plfe/rpc HTTP/1.1

ボディ
<いろんなバイナリ情報>
google
   eyJhbGciO....snip.... <- div="" id_token="" post="">


と、いうことでやっぱり OpenID Connect でのログインおよびメールアドレス情報だけを渡している、ということで、まぁ大丈夫そうです。


◆まとめ

今回はあくまでサインアッププロセスのみを見ているので、続く処理で何が行われているかはわかりませんが、とりあえずという意味では以下のことが言えると思います。

  • Pokemon Go のログイン・サインアップには OpenID Connect が採用されている
  • email アドレスのみを読み取る Scope で access_token が要求されているが、実際は id_token だけが使われている
  • 結果、メールアドレスくらいしか連携されていなさそうなので、別アカウントを作ったりする程にセンシティブにならなくてもよさそう?


注記)
  • 解析はあくまで一部分のみを対象としているので、他の処理で色々と情報を収集している可能性があります
  • 本解析は Pokemon Go のサービスを攻撃することを意図したものではありません
  • 本ポストが Pokemon Go のサービス規約に違反するなどし、サービス提供者の意図にそぐわない場合は本ポストを削除する可能性があります

0 件のコメント: