- EA認証・ゲートウェイAPIの公開されたSwaggerドキュメントと、persona更新時の権限検証不備が組み合わさり、他ユーザーのアカウントデータやログインフローにまで影響を及ぼし得た
- 核心は
/identity/pids/{pidId}/personas/{personaId}のPUTリクエストが、一般的なEA Desktop OAuthクライアントのdp.client.defaultスコープでアクセス可能であり、本文のpidIdとパス上のpersonaIdの所有権チェックが不十分だった点にある
- 攻撃者は、personaのユーザー名変更、
BANNED状態の設定、personaの移動、非公開アカウントのpersona ID検索、Xbox personaを使ったログイン回避を組み合わせ、最終的にアカウントのWebログインに到達できた
- 影響範囲は、ユーザー名・一部ゲームデータの窃取、オンラインゲーム接続妨害、ゲームBANの回避、Xbox経由でのEAアカウントログインにまで及び、深刻度はCVSS 10.0と評価された
- 脆弱性は2024年6月16日にEAへ報告され、EAは6月25日にcriticalへ分類、その後7月8日から10月8日にかけてpersonaの所有権チェック追加やドキュメント削除を含むパッチを展開した
EA認証環境から始まったAPIドキュメント露出
- EA Desktopで発見された開発環境integrationのテストが出発点だった
- 本番認証APIは
accounts.ea.com
- integration認証ホストは
accounts.int.ea.com
- integration環境で権限付きaccess tokenを取得でき、このトークンでアクセス可能なAPIを確認するため、公開されているドキュメントの探索が始まった
- 認証エンドポイントはreverse proxyの背後にあり、
/connectパスと通常の/パスでは404応答の形式が異なり、serverヘッダーはistio-envoyだった
/connect/api-docsは他の/connect配下パスと異なり空の404を返しており、別サービスへルーティングされている可能性が見え、/connect/api-docs/index.jsonでSwagger 1.1ドキュメントが見つかった
- Swaggerドキュメントは
/api-docs/connectを指しており、これをswagger-codegen-cliでOpenAPI 3.0仕様へ変換し、ローカルのSwagger UIで確認した
Gatewayで判明した内部API一覧
- EA Desktopは「Service Aggregation Layer」というGraphQL APIを使っているが、integration環境のSALはファイアウォールの背後にあった
- 旧バージョンと見られる
gateway.ea.comのgateway APIは、proxy/{service}/{route}形式のエンドポイントを使っていた
gateway.int.ea.com/proxy/api-docs/index.jsonは80以上のサービスドキュメント一覧を返した
addresses、agerequirements、billing、commerceなど複数のサービスが含まれていた
- 各APIドキュメントを取得して最新のOpenAPI仕様へ変換した後、アクセス可能な機能を確認した
- 一部エンドポイントはEAゲームチーム関連の「projects」データを返し、
basic.domaindata権限スコープが必要だった。さらに本番環境でそのスコープを持つクライアントも見つかった
- サンプルデータには、中止されたStar Warsゲームや、Apex Legendsが
Titanfall3関連グループ名で表示されている項目があった
- integration環境では、カスタムゲームentitlementを付与する方法も文書化されていたが、ダウンロードやプレイに必要なintegrationサービスはファイアウォールの背後にあり、実用性は低かった
- Xbox Live Server Tokenを返すエンドポイントもあったが、sandbox IDが
RETAILではなかったため、それ以上の調査は行われなかった
本番アカウント情報とpersona構造
- ドキュメント内の各エンドポイントには必要な認証スコープが示されており、検証は本番OAuthクライアントでアクセス可能なエンドポイントを中心に進められた
/identity/pids/meはアカウントの一般情報を返す
- メールアドレスのマスク値、メール状態、生年月日の一部、国、言語、アカウント状態、利用規約バージョン、作成・更新・最終認証時刻、2FA有効化の有無などが含まれる
/identity/pids/me/personasはアカウントに紐づくpersona一覧を返す
- 基本のEAアカウントは
cem_ea_id namespaceを使う
- Steam、Xboxなど接続された外部アカウントもそれぞれpersonaとして表示される
- ゲームは通常、統計やインベントリのようなデータをpersona配下に保存できるため、プラットフォームごとにデータが分離され得る
- 以後、
cem_ea_id namespaceのpersonaを「Origin」personaと呼称する
中核の脆弱性: persona更新時の権限検証不備
/identity/pids/{pidId}/personas/{personaId}エンドポイントはGET、PUT、DELETEリクエストを受け付ける
- PUTリクエストは
dp.client.defaultとdp.server.defaultスコープを許可しており、一般的なEA Desktop認証クライアントがdp.client.defaultを持っていた
- リクエスト本文では
displayName、namespaceName、status、statusReasonCode、lastAuthenticated、nickName、pidIdなどを受け取れた
- 自分のOrigin personaに対して
displayNameを変更するPUTリクエストは成功し、EAアカウントWebサイト上のユーザー名が変更された
- このリクエストは、ユーザー名変更のクールダウンと、ユーザー名変更時のメール確認を回避した
namespaceName変更には効果がなかった
status値にはACTIVE、DISABLED、PENDING、DELETED、BANNEDが指定でき、自分のOrigin persona状態をBANNEDに変更すると、EA Desktopは引き続き使えた一方でゲームログインは遮断された
- より大きな問題は、リクエスト本文のpidIdを他人のアカウントIDに変更できたことだった
- 自分のSteam personaを友人のEAアカウントへ移動させるリクエストが成功した
- その後、再び自分のアカウントへ戻すことも可能だった
ログイン検証とXSSの試行
- 自分のSteam personaを友人アカウントへ移した後、SteamでEA Webサイトへのログインを試すと、新しい場所・信頼されていないデバイスに基づくメール確認が表示された
- 表示されたメールの一部は自分のものではなく、友人アカウントへのログインフローまで到達していたが、位置ベースの2FA段階で阻止された
- personaのユーザー名を
BattleDash <script>alert(1)</script>の形に変更するリクエストも成功した
- アカウント連携ページでalertが実行され、XSSが可能だった
- ユーザーがEAアカウントにログインした状態でその連携ページへ誘導されると、ブラウザ上でコードが実行され、セッションを抽出できる状況だった
他人のアカウントのpersonaを直接操作
- パス上の
personaIdについても所有権検証が不十分か確認するため、自分が所有していないpersona IDでユーザー名変更を試した
- 新しいテストアカウントのpersona IDを取得後、被害アカウントの認証なしで、そのアカウントのユーザー名を変更するリクエストが成功した
- 同じ方法で
statusをBANNEDに変更でき、そのアカウントはゲームにログインできなくなった
/identity/personasはdisplayNameでpersonaを検索し、persona ID、アカウントID、作成日、最終ログイン時刻を返す
- ただし、アカウントを非公開にしているユーザーは表示されない
/identity/namespaces/{namespace}/personasは特定namespace内を検索し、ユーザー名とpersona IDのみを返すが、非公開アカウントも返す
- このエンドポイントだけでも必要なpersona IDを取得できた
persona移動の制約と部分的なアカウント乗っ取り
- 他人のOrigin personaを自分のアカウントへ移そうとすると、
TOO_MANY_PERSONAS_FOR_NAMESPACEエラーが発生した
- 自分のアカウントにすでにOrigin personaが存在していたためだ
- コンソールで登録したアカウントは、そのプラットフォームのpersonaのみを持ち、Origin personaを持たない場合があることに着目し、namespace衝突回避のためコンソールアカウントが使われた
- テストアカウントのOrigin personaをコンソールアカウントへ移し、その後被害アカウントのOrigin personaを自分のアカウントへ移す方法が可能だった
- この状態でログインすると、被害者のユーザー名、非クロスプラットフォームゲームの統計、一部のその他アカウント詳細が表示された
- 被害アカウントでログインすると、新規アカウント作成直後のようにユーザー名の選択を求める「Finish setting up my account」フローが表示された
- Battlefield 2042のような最新のクロスプラットフォームゲームのentitlement、フレンド、保存データはpersonaではなくEAアカウント自体に保存されており、移送されなかった
- それでも攻撃者は、ユーザーBAN、ゲームBAN回避、ユーザー名奪取、アカウントデータの人質化を実行できた
Xbox personaを使ったログイン回避
- この時点で可能だった操作は、自分のlinked account personaを任意のEAアカウントへ移すこと、任意のpersonaを自分のアカウントへ移すこと、personaのBAN・ユーザー名変更だった
- 他人のアカウントへログインしようとして自分のpersonaを移すと、メール確認が表示された
- コンソールでEAゲームをプレイする際には2FAプロンプトを見たことがない点に着目し、Xbox/PSNトークンベースのログインを調べた
- Nexus Connect APIドキュメントにはXbox/PSNトークンの受け渡し方法があり、EAサイトのPSNログインフローからPSN client IDを取得してPSNトークンログインを試した
- PSNトークンログインでは
ps3 namespaceのpersonaが作成され、2FAなしでアカウントログインが可能だったが、dp.client.defaultを持つクライアントではps3 namespaceを扱えなかった
/connect/tokeninfoにX-Include-Namespaceヘッダーを追加すると、OAuthクライアントごとに操作可能なpersona namespace一覧があることが確認できた
- 例の
JUNO_PC_CLIENTにはcem_ea_id、steam、epic、xbox namespaceが含まれていた
- Xbox namespaceは許可されていたが、有効なゲーム用Microsoft XSTSトークンを手動生成できなかったため、実機のXboxでテストした
- 新しいMicrosoftアカウントを作成し、そのXbox personaをテスト用EAアカウントに接続した後、そのXbox personaを被害者アカウントへ移動した
- EA WebサイトでXboxアカウントとしてログインすると、新しい場所のメール確認が出たが、XboxにBattlefield 2042をインストールしてゲームへログインすると、被害者アカウントとして接続された
- その後、同じXboxアカウントでEA Webサイトへログインした際にはメール確認なしで、被害者アカウントのWebログインにまで成功した
影響範囲と深刻度
- 攻撃者が使える主要ルートは2つあった
- 他人のpersonaデータをアカウント外へ移し、ユーザー名とゲームデータを窃取する
- 自分のXbox personaを被害者アカウントへ移し、XboxでEAゲームにログインした後、ネットワークが信頼済み状態になるとXboxアカウントでEA Webサイトへログインする
- 追加の影響も大きかった
- 他人のpersonaをBAN状態にして、ほとんどのオンラインゲームプレイを妨害できる
- 他人のユーザー名を変更した後で自分がその名前を取得できる
- ゲームBANがアカウント全体のゲームentitlement無効化として処理されるため、personaを新しいアカウントへ移すことでゲームBANを回避できる
- このフローは、ユーザー操作なしで主に単一のAPIエンドポイントを通じて実行可能だった
- 深刻度は
AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H基準でCVSS 10.0と評価された
修正スケジュールとその後の見解
- 脆弱性は2024年6月16日にEAへ報告された
- EAは2024年6月25日に確認を返し、critical深刻度を付与した
- パッチ日程は次のとおり
- 2024年7月8日: Patch 1展開、persona ownership check
- 2024年7月18日: Patch 2展開、詳細不明
- 2024年9月6日: Patch 3展開、詳細不明
- 2024年9月10日: Patch 4展開、ドキュメント削除
- 2024年10月8日: Patch 5展開、詳細不明
- EAの当初見積もりでは、修正は年末までかかる可能性があるとされており、公開ドキュメントと単一の危険なエンドポイントが核心である事案では、より迅速な暫定パッチが望ましかったとの評価が示された
- EAにはまだbug bountyプログラムがなく、実質的な報告報酬がない場合、脆弱性を非公開のまま保持する人が出る懸念が残る
- 初期テストに使われた友人アカウントは同意を得たアカウントだった
1件のコメント
Hacker News の意見
EA は複数のゲームで共通システムを使うのが好きです。Madden を調べていたら、
blazeという共通バックエンドがあり、汎用の Web/TCP エンドポイントがあることに気づきました。このエンドポイントを呼び出すツールを作ったのですが、XML をアップロードする必要があり、後で分かったことには、呼び出すたびに EA のサーバーが落ちていました。
リクエストごとに新しいサーバーをつかんでいたため、Madden のサーバーを一つずつ全部クラッシュさせていたわけで、最終的に EA は人々に詮索されないよう API を作りました。
記憶では、プレイヤー 5,000〜1万人あたり Blaze インスタンスが 1つ程度必要でした。
現在は独自フォーマットを使っていて、誰もインターフェース方式を解明できないだろうと仮定するようなセキュリティ、つまり曖昧さに依存したセキュリティに、かなり安住していたように見えます。
いつかその記事に戻りたいですし、少なくともかなり面白い内容があります。
こうした有名サービスの API をリバースエンジニアリングするときのコツは、GitHub のコード検索を使うことです。固有のエンドポイント名を入れてみると、自分で小さな API クライアントをハックして作った似たような人たちがよく見つかり、思いもよらない形で調査の助けになります。
namespacenameの値が返ってきます。2FA トークン情報は JUNO から取得した/tokeninfo/エンドポイントでハッシュ化されるはずです。事後統合を試すと、C++ API 用インフラが PSN ユーザー ID を返すことがよくありました。
普通の人なら当然そうしたでしょうが、Xbox を翌日配送で注文し、Battlefield 2042 をインストールして決定的瞬間を待ち、入ることができました。
ハッカーたちは本当に最高です <3
ある地点から次の地点へどう移動したのか、その詳細な流れが面白かったです。ブログ記事のようにきれいな一直線ではなかっただろうと思います。
こうした攻撃に実際どれだけの時間と労力がかかるのかを示すには、おそらく山のようなメモがあるはずで、それを見るのも興味深そうです。
この一連の中で最も奇妙なのは、EA が既存の Xbox アカウント連携を解除して新しいアカウントに再連携することは、何年もの間技術的に不可能だと主張してきた点です。https://www.reddit.com/r/XboxGamePass/comments/12gsy4i/ea_xb... のような投稿や、EA フォーラムの多数の投稿を見れば分かります。
私もこの壁にぶつかり、EA サポートと何時間も通話しましたが、非常に古い Xbox アカウントを連携してもらうことはできませんでした。そのため Xbox ではどの EA ゲームにもログインできず、そのプラットフォーム上ではほとんどプレイできなくなりました。
ところがここでは、十分に可能であることが明らかになっています。
不思議なことに私のアカウントはあまりに時間がかかり、1〜2年の間に何度もサポートにメールしましたが、毎回、できるだけ早くアカウントをアップグレードしているものの作業が非常に大規模なので数年かかる、という返事でした。
後にあるフォーラムで、アカウントを一時的に閉じてから再び開くと 25MB には増やせるという抜け道を見ましたが、約束された 250MB ではありませんでした。
既存アカウントは 2〜4MB、新規アカウントは 25MB、250MB までは数年がかりの配布という状況は、Microsoft が余った保存容量を見つけるのに途方もなく苦労しているという印象を与えました。ところが数か月後、Gmail と競争しなければならなくなると、全員に 2GB を提供することにし、私のアカウントを含むすべての Hotmail アカウントに一度に配布されました。宇宙人がハードディスク満載の UFO を持ってきたに違いありません。
[1] その抜け道についての古いフォーラム投稿の例で、新しく出た GMail を称賛する返信もあります: https://bimmersport.co.nz/topic/5232-hotmail-upgrade-2mb-to-...
連携変更が課金システムに保存されたデータを無効化したり、Microsoft の Xbox 部門に送る月次レポートを壊したり、内部管理ページが読み込み中にクラッシュする原因になったりするかもしれません。
EA を擁護するつもりはありませんが、複雑なマイクロサービスシステムを多く扱っていると、ある場所のデータ構造を変えることが常に単純とは限りません。
すべてのアカウントをBANして、DBバックアップがないことを願うのも面白かったかもしれない
金を払っている顧客として、こうした企業にはもっと良い姿勢を期待するし、プログラムがないなら、ハッカーが見つけたものを悪用しても個人的には責めない
4億件のレコードを単一のマシンに保存する人はいないし、結局サービスを午後いっぱい落としたうえで、連邦刑務所15年を食らうだけだ
何百万人にも被害を与えて、その人たちが取引していた会社に教訓を与えるのが「面白そう」という発想が最初の反応、少なくとも今いちばん評価されている投稿だという点だ
記事にこういう箇所がある:
I had found a way to obtain a privileged access token within the environment (a story for another day, but a certain game's executable had hardcoded credentials!), but I wasn't sure what I could do with it.この部分をもう少し説明してもらえる?実行バイナリからそんな認証情報を簡単に読み取れるべきではないと思っていたし、ゲームの実行ファイルがリモートサーバーに自分自身を認証しなければならないなら、開発者が他に何をすべきなのかもよく分からない
クライアント・サーバー構成では、クライアントは常に信用できない。実行ファイルがサーバーに自分自身を認証する必要があってはならない。実行ファイルは、ユーザーが提供した情報でユーザーまたはアカウントとして認証すべきだ
テレメトリのような場合、こうしたエンドポイントは通常、認証なし、または弱い認証のデータを受け取り、悪用を防ぐために複数段階の検証を行う。たいていは書き込み/追記専用でもある
実行ファイルを暗号化し、CPUダイ上のセキュア領域が秘密鍵で復号を処理するシステムが必要になるだろうが、それでも誰かがチップをデリッドして鍵を手に入れるのは時間の問題である可能性が高い
暗号化して暗号鍵をHSMに入れたとしても、任意のクライアントマシンではおそらく不可能なうえ、どこかの時点でゲームはその文字列を復号してメモリに載せなければならない。そしてそのメモリは読める
ゲーム開発者がすべきことは、バックエンドにアカウントシステムを置き、プレイヤーがゲーム内で自分の認証情報を入力するようにすることだ。そうすればゲームは、バックエンドサーバーに対してこのプレイヤーとして自分を識別できる
こうして初めて、バックエンドでの行動を特定のプレイヤーに帰属させられ、セキュリティ判断を下すための良い基盤ができる
IDAのようなツールがあるので、文字列に見えるものすべての中から肉眼で認証情報を探すわけでもない
問題は、バイナリにハードコードされた認証情報があること自体より、その認証情報が特権権限を持っていることだ
こういう会社のエンジニアとして、非公開APIや変なバグ、汚い内情が公開の侵害報告書に出てくるのはどんな気分なのか、ときどき気になる
ただしこういう場合、単一の個人が脆弱性の責任者だった可能性は低い。おそらく5〜6つのチームが、悪用された別々の部分を所有していて、そのためにそもそもエクスプロイトが存在したのだろう。誰もが自分の小さな部分だけを理解している、巨大で複雑なシステムだから
EAほどの規模の会社では、ほぼ確実にこの件は社内政治に使われるし、会社全体には害になっても、人々はより小さくなった会社に対するより大きな支配権を得るために利用するだろう
皆が置き換え可能なリソースなのに、なぜ仕事に感情的に入れ込むのか
当時のチーム名はNucleusで、だから記事のレスポンスの一つで
refTypeがNUCLEUSだった。このチームは権限、アカウント、決済用のバックエンドAPIを作って管理していた夏のインターンシップで、1年後にそのチームからオファーを受けて働き始めた。そのときにはチーム名がEADPに変わっていて、Originとゆっくり統合されているところだった。DPがData Platformだったかは記憶が曖昧だが、それでエンドポイントの一つが
dp.で始まっている当時はGraphQLデータベースはなく、すべてEnterprise Java、OCI、Spring、Hibernateなどで、辞める前にはより新しいGroovy/SpringBootも一部あった。クラウドではなくデータセンターのサーバーで動いていた
それでも面白い仕事をしていたし、大きな事故が起きてから2〜3年で辞めたが、優秀なエンジニアたちからバックエンド開発を多く学んだ
今のチームがどうなっているのか、エンジニアが誰なのか、何が起きているのかはまったく知らないが、こういうものを見ると残念だ。当時の私たちはセキュリティを非常に意識していて、ログインページへのブルートフォース試行を検知して処理するシステムにも取り組んでいた
まだ有効なのか稼働しているのかは分からないが、侵害の可能性と攻撃対象領域を減らすためのセキュリティチェック/レビューがスプリント作業の一部だった
この記事を面白く読んだなら、HackerOne の Hacktivity のようなバグバウンティプラットフォームでもっと多く見られる: https://hackerone.com/hacktivity
数週間または数カ月ごとに更新される
バグバウンティプログラムを設定するためのベストプラクティスガイドはどこかにある?
Webサイトのどこかに、調整された脆弱性開示手順に従うことを条件に技術的なセキュリティ検査をしてよいと掲示し、どの範囲のどのバグに対してどんな報酬を出すかを書けばよい。もちろん、この一文よりはもう少し具体化する必要がある
年齢が若すぎる、または高すぎる場合は支払わないとか、制裁対象となる国で生まれていてはいけないとかいった例外も、後で感情的なしこりを残さないように先に書いておくほうがよい
具体的な質問があれば答えられるし、よい参考資料を探すこともできる
記事のこの部分を見ると:
It's also disappointing that EA has yet to start a bug bounty program. Without any real incentive to report vulnerabilities, I know people who have instead chosen to keep them to themselves. I would love to see EA follow the rest of the industry's lead here.つまり著者はこれを報告して何も受け取れなかったということ?
報告には法的リスクがあり、技術的には企業が最後まで訴訟を起こせるという点も助けにならない。EU/UK基準での話だ