ブログ

Pokémon Go API – 自動化された攻撃の詳細

F5 サムネイル
F5
2016年8月16日公開

何千万人もの人々がポケモンGOの新しい世界を探検しています。 実は、それらのユーザーの多くは人間ではなく、自動エージェント、つまりボットであることが判明しました。 ゲームをプレイするボットは新しい現象ではありませんが、Pokémon Go はボットの新しい使用例をいくつか提供しています。 これらのボットは、自動化されたトラフィックでPokémon Goサーバーを圧倒し、みんなの楽しみを邪魔し始めています。 Pokémon Go は、モバイル API 上で自動化された攻撃と防御がどのように機能するかを示す完璧なケーススタディです。 Shape では、このような種類の攻撃に毎日対処しているので、Pokémon Go API 攻撃で何が起こったのかを詳しく調べてみようと思いました。

ポケモンGO API攻撃

Niantic は最近、ボットが自動トラフィックを生成することで引き起こし、実際にラテンアメリカでの展開を妨げていた問題について詳述したブログ記事を公開しました。 投稿に含まれるグラフは、Niantic が 8 月 3 日午後 1 時 (太平洋標準時) に自動化に対する対策を展開して以来、空間クエリ トラフィックが大幅に減少したことを示しています。 自動化されたトラフィックは、実際の人間のプレイヤーからのトラフィックの約 2 倍であったようです。 ここ数週間、ポケモンGOのサーバーが過負荷状態になったのも不思議ではない。

 

サーバーリソース
図1. Niantic がスクレイパーをブロックし始めてから、空間クエリのトラフィックは 50% 以上減少しました。 ソース: Nianticのブログ投稿

ポケモンボットを知る

ポケモンボットには2種類あります。 最初のタイプのボットは通常のゲームプレイを自動化し、他のゲーム アプリでよく見られるもので、歩き回ったりポケモンを捕まえたりするアクティビティを自動化します。 このようなボットの例としては、MyGoBot やPokemonGo-Bot などがあります。 しかし、ポケモンGOは、ポケモンの位置を提供するトラッカーまたはマッパーと呼ばれる新しいタイプのボットの開発に影響を与えました。 これらのボットは、 PokevisionGo Radarなどの Pokémon Go マッピング サービスに力を与えています。

ポケモンGOボットの仕組み

モバイル API ボットは、モバイル アプリとそのバックエンド サーバー (この場合は Niantic のサーバー) 間の通信を模倣するプログラムです。 ボットは、実行されるアクションをサーバーに伝え、サーバーの応答を消費するだけです。

図 2 は、特定の場所から 3 フィートの範囲内の近くのポケモンをマークする Pokémon Go マップのスクリーンショットを示しています。 これを実現するために、ボット作成者は通常次の手順に従います。

  1. モバイル アプリとバックエンド サーバー間の通信プロトコルをリバース エンジニアリングします。 ボット作成者はゲームをプレイし、アプリとサーバー間の通信をキャプチャし、プロトコル形式を解読します。
  2. バックエンド サーバーに一連の「正当な」リクエストを送信してアクションを実行するプログラムを作成します。 この場合、近くのポケモンの位置を取得するには、物理的な場所まで実際に歩くことなく、対象の GPS 座標を指定した単一のリクエストで済みます。 ボットにとっての課題は、サーバーの検出を回避し、本物の人間のように見えることです。
  3. Google マップとの統合などの関連機能を提供したり、ユーザー向けにボット独自のマッピング機能を組み込んだりします。

地図
図2. ポケモンGOマップのスクリーンショット

モバイルアプリのクラックと防御

Pokémon Go アプリを例に、リバースエンジニアリングによってモバイル アプリがクラックされ、その秘密が明らかになる仕組みを調べてみましょう。 攻撃者は主にPokémon GoのAndroidアプリを悪用していたため、Androidアプリのクラックと防御に焦点を当てましょう。

プロトコルのリバースエンジニアリング

Pokémon Go アプリとバックエンド サーバーは、SSL 経由のProtoBuf を使用して通信します。 ProtoBuf は、ネットワーク上で転送されるデータ形式を定義します。 たとえば、プレーヤーの統計情報の ProtoBuf 定義の抜粋を次に示します。

プレイヤー統計の ProtoBuf 定義

ポケモンGOは、 POGOProtosによってわずか2週間以内にリバースエンジニアリングされ、オンラインで公開されました。 どうしてこんなに早く起こったのでしょうか? 当初、Niantic は証明書ピンニングを使用していませんでした。

証明書ピンニングは、中間者攻撃に対抗するために使用される一般的なアプローチです。 つまり、モバイル アプリは、アプリ自体に埋め込まれているサーバー証明書のみを信頼します。 証明書ピン留め保護がなければ、攻撃者はMitmproxyFiddlerなどのプロキシを簡単にセットアップし、攻撃者が作成した証明書を携帯電話にインストールできます。 次に、彼女は自分の携帯電話を設定して、トラフィックをプロキシ経由でルーティングし、Pokémon Go アプリと Niantic サーバー間のトラフィックをスニッフィングすることができます。 実際に、これを可能にするpokemon-go-mitmと呼ばれる Pokémon Go 専用のプロキシ ツールがあります。

7月31日、Niantic はサーバーと Pokémon Go アプリの両方に大きな変更を加えました。証明書ピン留め保護を備えた Pokémon Go 0.31.0 がリリースされました。 残念ながら、秘密は漏れてしまい、通信プロトコルはすでに GitHub で公開されていました。 さらに、証明書ピンニングを正しく実装することは必ずしも簡単ではありません。 後のセクションでは、証明書のピン留めを回避するために攻撃者がよく使用するいくつかの手法について説明します。

APK 静的解析

Android アプリケーション パッケージ(APK) は、 Androidがモバイル アプリをインストールするために使用するパッケージファイル形式です。 Android アプリは主に Java で記述されており、Java コードはdex 形式にコンパイルされ、apk ファイルに組み込まれます。 さらに、Android アプリはネイティブ コード ( Android NDK ) で記述された共有ライブラリを呼び出すこともできます。

Dex ファイルは、 Baksmaliなどのツールを使用して、簡単に SMALI 言語に逆アセンブルできることが知られています。 次に、 dex2jarjd-guiなどのツールが dex ファイルを読みやすい Java コードにさらに逆コンパイルします。 攻撃者はこれらの手法を使用して、Pokémon Go Android アプリ (バージョン 0.29.0 および 0.31.0) を Java コードに逆コンパイルしました。 以下に示すサンプル コードはcom.nianticlabs.nia.network.NianticTrustManagerクラスからの証明書ピン留めを実装します。

サンプルコード

アプリケーションのソース コードが公開されると、リバース エンジニアリングが簡単になります。 Pokemon Go Xposed は、 100 行未満の Java コードを使用して、MITMProxy からの証明書が Niantic からの本物の証明書であると Pokémon Go アプリに信じ込ませました。

Pokemon Go Xposed はどうやってこれを達成したのでしょうか? かなり簡単に。 このツールは、上記のコード スニペットに記載されている関数checkServerTrustedの呼び出しに単純にフックします。 フックは、関数の最初のパラメータchain をNiantic の証明書の値に変更します。 つまり、プロキシがどのような不正な証明書を使用していても、Pokémon Go アプリは騙されてその証明書を信頼してしまうことになります。

攻撃者による逆アセンブリや静的分析を困難にするのに役立つツールは数多くあります。 ProGuardDexGuard は、 Java コードと dex ファイルに難読化を適用するツールです。 難読化により、逆コンパイルされた形式であってもコードが読みにくくなります。 もう 1 つの方法は、 Android パッカーを使用して Android アプリの元の classes.dex ファイルを暗号化することです。 暗号化された dex ファイルは実行時にメモリ内で復号化されるため、ほとんどの攻撃者にとって静的分析は不可能ではないにしても極めて困難になります。 ネイティブ ライブラリを使用することは、アプリのリバース エンジニアリングの難易度を大幅に高めるもう 1 つの方法です。

ネイティブライブラリのリバースエンジニアリング

pokemongodevハッカーと Niantic の間で最も興味深い追いかけっこが繰り広げられたのは、「Unknown6」というフィールドをめぐるものでした。このフィールドは、ある場所で近くのポケモンを入手するためのマップ リクエストで送信された署名に含まれていました。 「Unknown6」は、リバースエンジニアリングされた protobuf 内の未識別フィールドの 1 つです。 当初、Unknown6 にどのような値が与えられたかは問題ではなく、Niantic サーバーはそれをそのまま受け入れました。 8 月 3 日午後 1 時 (太平洋標準時) から、すべての Pokémon Go ボットが突然ポケモンを見つけられなくなり、最終的に図 1 に示すようにクエリ数が大幅に減少しました。

その後、ハッカーはプロトコルの「Unknown6」フィールドの重要性に気づき、当初はUnknown6がリクエストの整合性を検証するための何らかのダイジェストまたはHMACであると疑いました。 これはポケモンGO開発コミュニティから大きな関心を呼び、この謎の分野を解明しようと「Unknown6」チームがすぐに結成されました。 Discordチャンネルは、コーダーと非プログラマーからの幅広い関心により非公開になりましたが、ライブ更新チャンネルによって、クラッキング作業の進捗状況が全員に最新の状態で提供されました。 3日と5時間後、8月6日の午後、Unknown6チームが勝利を宣言し、再び近くのポケモンを取得できる更新されたPokémon Go APIをリリースしました。

ハッキングの詳細に関する技術的な記述はまだ公開されていないが、フォーラムやライブアップデートでは多くの関連ツールやテクノロジーが言及されている。 IDAプロ Hex-RaysのARMコードはネイティブライブラリの逆アセンブルが可能なプロフェッショナルツールであり、新しい Hex-Rays デコンパイラ バイナリ コード ファイルを C スタイルの形式に逆コンパイルできます。 これらのツールを使用すると、攻撃者は動的分析を実行し、実行時にモバイル アプリとそのライブラリをデバッグできます。 もちろん、このような強力なツールがあっても、バイナリ プログラムをリバース エンジニアリングするのは依然として非常に困難です。 意図的な難読化を行わないと、逆アセンブルまたは逆コンパイルされたコードは理解しにくくなり、コード サイズが巨大になることがよくあります。 必要となる複雑で予測不可能な作業の例として、ライブ更新チャンネルとその後のインタビューでは、「Unknown6」の暗号化機能が数時間で特定されたが、チームは「Unknown22」という別のフィールドの分析にさらに長い時間を費やし、それが後にUnknown6とは無関係であることが判明したことが説明されました。

その結果、難読化にはネイティブ ライブラリを保護するための実用的な利点が依然として多くあります。 バイナリの難読化レベルが高いと、リバースエンジニアリングの難易度が桁違いに高くなる可能性があります。 しかし、Windows および Windows アプリケーションのシリアル コードのクラックが多数成功していることからもわかるように、意欲的なモバイル クラッカーは成功することが多いのです。

サーバー側の保護

サーバー側の防御は、クライアント側の防御とはまったく異なる方法で機能します。 ここでは、Pokémon Go のモバイル API を保護するために使用されているテクニックの一部を紹介します。

レート制限

レート制限は、自動化されたトラフィックを停止するか、少なくとも速度を低下させるための一般的なアプローチです。 初期のポケモン スキャナーは、1 秒あたり数十件のリクエストを送信し、数十個のセルをスキャンして、すべてのポケモンを見つけることができました。

7 月 31 日に、Niantic はレート制限保護を追加しました。 1 つのアカウントが約 5 秒以内に複数のマップ リクエストを送信した場合、Niantic のサーバーは最初のリクエストのみを受け入れ、残りをドロップします。 攻撃者は、これらのレート制限に対して、次の方法で対応しました。a) スキャンプログラムからのマップ要求の間に遅延(5秒)を追加するb) 複数のアカウントと複数のスレッドを使用してレート制限を回避する

Pokémon Go の場合、レート制限の使用により、自動アカウント作成という、自動攻撃の新たな戦場が開かれたことになります。 彼らはすぐに、レート制限は過度に攻撃的なスクレーパーや初心者の攻撃者からの自動化を制御するための優れた基本的手法である一方で、高度な攻撃者が自動化されたリクエストを通過させることを阻止することはできないことを発見しました。

IP ブロッキング

IP のブロックは、疑わしい IP からのリクエストをドロップするために標準のネットワーク ファイアウォールまたはWeb アプリケーション ファイアウォール(WAF) で使用される従来の手法です。 IP レピュテーションを追跡するデータベースは多数あり、ファイアウォールと WAF はそのような情報を定期的に取得できます。

一般的に、IP ベースのブロックはリスクが高く、効果がありません。 大量のトラフィックがある IP を盲目的にブロックすると、大学や企業の NAT がブロックされてしまう可能性があります。 一方、多くのポケモン ボットやスキャナーは、住宅の動的 IP アドレスを使用する場合があります。 これらの IP は ISP の顧客によって共有されるため、IP を長期間禁止すると正当なプレーヤーがブロックされる可能性があります。

Amazon Web Services (AWS) や Digital Ocean などのホスティング サービスも、攻撃者が仮想マシンや新しい IP を入手するための情報源となります。 攻撃者が盗んだクレジットカードを使用すると、これらのリソースを無料で入手することもできます。 ただし、正当なユーザーがホスティング サービスを使用して Web を閲覧したりゲームをプレイしたりすることは決してないため、ホスティング サービスからの IP をブロックすることは安全な防御であり、サーバー側でよく使用されます。 このフォーラム投稿によると、Niantic は AWS から IP を禁止することを決定する可能性があります。

行動分析

動作分析は通常、他の防御を回避できる高度な攻撃者に対する最後の防御線となります。 ボットの行動は人間とは非常に異なります。 たとえば、実際の人間はゲームを 24 時間 365 日プレイしたり、1 秒間に 5 匹のポケモンを捕まえたりすることはできません。 行動分析は有望なアプローチのように思えますが、Pokémon Go のような膨大なデータ量を処理する正確な検出システムを構築するのは簡単なことではありません。

Niantic は、GPS スプーフィングを使用して「テレポート」(つまり、突然信じられないほどの高速で移動すること)する不正行為者に対してソフト バンを実施しました。 これはおそらく誤検知による「ソフトバン」だったのでしょう。家族でアカウントを共有しており、GPS の読み取りが不正確な場合があり、正当な使用例がボットのように見えることがあります。

2016年8月12日頃、Nianticは自社のウェブサイトに注意事項を掲載し、利用規約に違反した場合はPokémon Goのアカウントが永久に禁止される可能性があることを説明した。 ボットを対象とした複数の禁止ルールも非公式に公開されました。 たとえば、ポケモンの過剰捕獲ルールでは、1 日に 1,000 匹を超えるポケモンを捕獲するとアカウントが禁止されます。 さらに、Niantic は正当なプレイヤーに対して、不正行為者や不適切なプレイヤーを報告するよう奨励しています。

私たちの経験では、行動モデルに基づく検出は非常に効果的ですが、社内で構築するのは技術的または経済的に不可能な場合が多いです。 Niantic がブログ投稿でコメントしているように、「この問題に対処するには機会費用もかかります。 開発者は、新しい機能を構築するのではなく、この問題を制御することに時間を費やす必要があります。」 さらに大きな問題は、通常の防御を回避するように設計されたボットネットやその他のツールを装備した、技術に精通した熱心な敵から身を守るためのテクノロジーを構築するには、多くの高度に専門化されたスキルセットと膨大な開発努力が必要になることです。

ゲームはまだ終わっていない

ポケモンGOがプレイヤーに愛され続ける限り、ボットメーカーとナイアンティックの争いも続くだろう。 自動化されたトラフィックに対する防御は、ゲーム業界だけでなくすべての業界にとっての課題です。 同様の攻撃と防御活動は、数匹のカビゴンを失うよりも桁違いに大きなリスクを伴う銀行、航空会社、小売業のアプリでも行われています。 ボットや関連する攻撃ツールは、不要な自動トラフィックのせいで顧客やユーザーがサービスにアクセスできない場合、企業にとって楽しいものではありません。