世界を動かす技術を、日本語で。

任意のGoogleユーザーの電話番号をブルートフォース攻撃で特定する

概要

  • Googleアカウントの ユーザー名回復フォーム が、JavaScript無効でも動作することを発見
  • BotGuardトークン の仕組みを利用し、電話番号のブルートフォース攻撃が理論的に可能
  • IPv6アドレス の大量利用でレートリミット回避を試みるも、追加の対策あり
  • Looker Studio経由で 表示名リーク が可能
  • ベンダーへの報告と 対応のタイムライン を記載

Googleアカウント ユーザー名回復フォームの脆弱性調査

  • 2024年時点で、Googleの ユーザー名回復フォーム がJavaScript無効でも利用可能
  • 通常、 BotGuard によるJSベースの証明が必要と考えられていたが、No-JSフォームも動作
  • フォームは、 リカバリーメールや電話番号 が特定の表示名に紐付いているか確認可能
  • 2つのHTTPリクエストで判定
    • 1回目:リカバリー情報入力で ess値 取得
    • 2回目:ess値と表示名でアカウント存在確認
  • レスポンスのリダイレクト先で アカウント有無判定

ブルートフォースの可否とレートリミットの回避

  • 通常は IPアドレス単位でレートリミット +CAPTCHA表示
  • プロキシ利用やIPv6アドレス大量生成 で回避を試みる
    • Vultr等のクラウドで/64レンジを活用し、 18京以上のアドレス でIPローテーション
    • 実際は データセンターIP には常時CAPTCHA表示で突破困難

BotGuardトークンの活用と突破方法

  • JS有効フォームで取得した BotGuardトークン をNo-JSフォームに流用
  • bgresponse=js_disabledBotGuardトークン に置換して送信→CAPTCHA回避に成功
  • レートリミットも実質無効化

実際のブルートフォース手法

  • オランダ携帯番号(+31 6xxxxxx03)のように 桁数が限られる場合、総当たりが現実的

  • gpbツール を使い、数千スレッドでチェック

  • ヒット時は、同一表示名・電話番号下2桁が一致するアカウントのみ

    • 表示名のみでヒットする場合もあるため、 ランダム姓でバリデーション を追加し精度向上

追加課題と最適化

  • 被害者の 国番号特定 は、Googleのパスワードリセット時の 電話番号マスク から判別可能
    • libphonenumbersの national format を利用し、各国のマスクパターンを収集
  • 表示名の取得 は2024年4月以降困難化
    • 例外的に Looker Studioの所有権移譲 で表示名リーク可能
  • libphonenumbers によるリアルタイムバリデーションで無効番号のAPIリクエスト削減
  • BotGuardトークン自動生成API も実装

攻撃チェーンまとめ

  • Looker Studioで 表示名リーク
  • パスワードリセットフローで 電話番号マスク取得
  • gpbツールで 総当たり攻撃実施

ブルートフォース所要時間の目安

  • $0.30/時サーバー(16vCPU)で 約4万件/秒 のチェック速度
  • 下2桁のみ判明時の所要時間例
    • 米国 (+1):20分
    • 英国 (+44):4分
    • オランダ (+31):15秒
    • シンガポール (+65):5秒
  • PayPal等他サービスのヒントでさらに高速化可能

ベンダー報告と対応タイムライン

  • 2025-04-14 :Googleへ報告
  • 2025-04-15 :トリアージ
  • 2025-05-15 :初回報奨金$1,337+スワッグ
  • 2025-05-22 :追加報奨金$3,663、合計$5,000+スワッグ
  • 2025-05-22 :緩和策導入・エンドポイント廃止開始
  • 2025-06-06 :No-JSフォーム完全廃止確認
  • 2025-06-09 :レポート公開

今後の課題・連絡先

  • 電話番号・表示名のリーク 対策の強化
  • BotGuardトークンの取り扱い 厳格化
  • 連絡先:筆者まで

Hackerたちの意見

2025-06-06 - ベンダーが、No-JSのユーザー名回復フォームが完全に廃止されたことを確認しました。だから、Googleの解決策はユーザー名回復にJSの使用を強制することなんだね。素晴らしい仕事だ、チーム /s

ログインするのにJSが必要だから、ノーJSのユーザー名回復フローにはあんまり価値がないね。

すべてのレガシーページを維持するのは本当に大変だろうね。長年続いているサイトが維持しなきゃいけない、あるいは維持することを選ぶ古いコンテンツの量は驚くほど多いし、それらを組み合わせてテストするのは不可能だよ。これらのアプリがどれだけ年齢層が多様かの例を見たいなら、Gmailの設定パネルを探ってみて。最終的には、2004年のオリジナルのGmailの見た目と感じを使ったポップアップにたどり着くはずだよ。

すべてのレガシーページを維持するのは本当に大変だろうね。2024年に3500億ドルの収益があっても、全然足りないみたいだね…

すべてのレガシーページを維持するのは本当に大変だろうね。Facebookの「ポーク」機能を誰が維持してるのか、いつも気になるよ。

だからこそ、企業は古い製品やサービスをどんどん廃止していくんだよ。「なんでそのままにしておけないの?」って思うかもしれないけど、そういうサービスは結局セキュリティホールになっちゃうから。安全なコードは、コードがないことなんだ。

バグバウンティプログラムは効率的な支出だと思う。数千ドルで、無給の人たちが極端なケースを探して問題を浮き彫りにしてくれるんだから。これを社員にやらせるともっとお金がかかるよ。

すべてのレガシーページを維持するのは大変な仕事だろうね。長年続いているサイトが維持しなきゃいけない、あるいは維持することを選ぶ古い情報の量は驚くほど多いし、それらを組み合わせてテストするのは不可能だよ。私が働いていた会社では、インターンや新入社員を使ってた。インターンプールに最初に与えられたタスクの一つは、ウェブサイトを見て古い情報や現在のブランドブックに合わないものを探すことだった。そのリストはどこかに送られて、ページが更新されたり削除されたりしてた。このやり方の大きな利点は、新しい人たちに私たちが何をしているのか、なぜそれをしているのか、そして製品の歴史の一端を見せることができることだった。

最終的には、2004年のオリジナルのGmailの見た目を使ったポップアップにたどり着くよ。実際、最近古い(2013年頃の)Catullのロゴが表示されたGoogleのページに遭遇したんだ。

今回は、PayPalなどの他のサービスのパスワードリセットフローからの電話番号のヒントで大幅に短縮できるかもしれないね。そこではさらに多くの数字が提供されるから(例:+14•••••1779)。こんなこと考えたことなかったけど、ちょっと怖いね。同じ電話番号とメールアドレスをいくつかのサービスで使ってて、それらがリセットヒントで違う順番でマスクされてたら…

リスクは何なの?メールが公開されること?それとも電話番号?

さらに怖いのは、これらのサービスの管理者にアクセスできる人が、マスクされていないデータを簡単に調べられるってこと!サービスごとにユニークな番号やアドレスを使った方がいいね。

今では、そんな情報を見つけるためのTelegramボットもあるよ。このブルートフォースが明らかになったことは、多くのユーザーをイライラさせたかもしれないね(悪名高い「EoG」ボットみたいに)。

過去には、サポートを受けるためにある会社にカードの下4桁を聞いて、それを別の会社で使うっていうソーシャルエンジニアリングの話がいくつかあったよね。

もし気が楽になるなら(多分ならないけど)、何百、何千ものサービスが年々あなたの電話番号を集めてきたよ(2FAや他の理由で)、同意があろうとなかろうとね。そして、その中のかなりの数がデータ漏洩を経験してる。だから、あなたの名前・メール・電話番号の組み合わせは、もう100%公開データダンプに載ってるよ。

大学にいたとき、クレジットカードについてのセキュリティ研究者の講演を聞いたことがあるんだけど、実際にそういうことがあったんだ。

こういうサービスは自動でやってくれるのがあって、結構前からあるよね。メールや電話番号、その他いろいろ。許可なしに(または相手が本当にその人だと信じられる場合以外)与えられた情報は、いろんなソースから効率よくまとめられちゃう。インセンティブがたくさんあるから、世界中で何十億人も使ってるサービスを狙ってる人がいるし、結局漏れちゃうんだよね。

うわ、これ以上にGoogleがゴーストシップだって証拠が必要なら、これだね。5,000ドルの報奨金は侮辱だし、最初から低い金額を提示したのが本当に滑稽に見える。ユーザーデータを守ることに対してGoogleがどれだけ無関心かを指摘してくれてありがとう。

バグバウンティに参加するのは誰も強制されてないよ。報酬が気に入らなかったら、やらなきゃいいだけ。こういうプログラムには、財政的な限界があるからね。

今日、新しいGoogleの製品について知ったよ。https://lookerstudio.google.com

あなたは、このソフトウェアのデモに参加するようにGCPの担当者にしつこく迫られなかったのは幸運だね。

自家製の製品じゃないよ。Lookerはデータ分析とビジュアライゼーションのための結構人気なツールで、昔にGoogleに買収されたんだ。

これめっちゃクリエイティブでクールだね。ブリュートキャット、またやってるね、へへ。

面白い発見だけど、電話番号ってみんな(このスレッドの人たちも含めて)大人になってからずっと友達や店、銀行、雇用主、政府機関、ランダムなウェブサイトに配りまくってるのに、まだそれが誰にも知られたくない重要な秘密だと思ってるのが面白いよね。電話番号は名前と同じくらいプライベートなもので、それをそう考えるべきだよ。

いや、そうじゃないよ。信頼できる人にだけ渡すもので、基本的にはその人たちがインターネットで公開するなんて期待してないよ。

うーん…これってそんなに衝撃的な意見じゃないよね。昔はみんなの電話番号や住所が載った本が出版されてて、番号を載せたくないならお金を払わなきゃいけなかったんだから。今って電話帳の概念が理解できない人がいるってこと?

だから、信頼できないサイトやサービスにはFirefox Relayのメールや電話のマスキングを使ってるんだ。もし無料の代替案を知ってる人がいたら教えてほしいな。電話のマスクはプレミアムプランが必要だから、友達や家族にはちょっと厳しいかも。

昔、誰かの電話番号を探そうとしてFacebookを使ったことがあるんだけど、パスワードを回復する時に電話番号のほとんどの数字を教えてくれたから、それをvCardファイルに書き留めて、携帯にインポートして写真を見るためだけに使ったんだ。意外と上手くいったよ。

Googleのプロフィール写真や他のGoogleアプリにも似たような穴があるよ。例えば、Googleマップでジョン・スミスのレビューを見たときに、Googleハングアウトでメールアドレスを追加して、johnsmith@gmail.comやsmithjohn@gmail.comみたいなバリエーションをいくつか試して、プロフィール写真を見比べるって感じかな。

この記事は面白いことを指摘してるね… ホスティングプロバイダーやISPから少なくとも1つの /64 IPv6 ブロックをもらうのは結構普通なんだ。でも、ほとんどのレート制限やIPブロックは単一のIPに対して行われてる。IPv6を扱うときは、/64全体をレート制限したりブロックしたりするべきだと思うんだ。

もしユーザーが1つのアドレスしか持ってなかったら、どうやって2つを分けるの?大きなブロック(プロバイダー)がブロック単位や単一アドレスで配布してるなら、共有する必要がありそうだね…

ほとんどの人が /64 でブロックすると思ってたんだけど。多分、/64ごとに異なる悪用やノイズのIPv6をカウントして、閾値に達したらブロックやスロットルするのが一番安全だと思う。/64からのIPv6ごとの悪用トラフィックの比率も、いい閾値になるかもしれないね。

彼がサーバーに対して1秒間に4万リクエストを長時間投げ続けられるってのに、リソースが急激に上がってアラームが鳴らないのがすごいと思う。

アラームが鳴った可能性もあるけど、その後すぐに行動が止まったから、警告レベルのページングには至らなかったのかもね。もしくは、たとえアラームが鳴ったとしても、ノートパソコンを開いてパスワードやOTPを入力して、リンクをたどってグラフを参照してる間に、リソースが数分で元に戻ったのかもしれない。ステータス更新が作成される前に、もうすでに落ち着いてきてるし。40kqpsって、FocusやGoogleのAPIの規模からすると、そんなに大したことないよね。ここで注目すべきは監視じゃなくて、以前のjs有効フローから借りたトークンを使ったjs_disabledフローのゼロレート制限だね。