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

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

2025年6月9日原文(brutecat.com)

概要

  • 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)。こんなこと考えたことなかったけど、ちょっと怖いね。同じ電話番号とメールアドレスをいくつかのサービスで使ってて、それらがリセットヒントで違う順番でマスクされてたら…

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

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

Hacker Newsで議論の続きを見る