900サイト、1億2500万アカウント、1つの脆弱性
(env.fail)- 誤って設定されたFirebase セキュリティルール1つが、数百のサイトにおけるユーザーデータの露出につながり、確認されただけで約1億2,460万件のレコードに達した
- 調査は、Webサイトと読み込まれたJavaScriptバンドルからFirebase設定変数を探す方法で始まり、Pythonスキャナーのメモリ問題によりGoで書き直された
- 補助スキャナーCatalystは、Firebaseコレクションが読み取り可能かどうかを自動確認し、サンプルデータをもとに露出した情報の種類と規模を推定する
- 集計された露出項目には、名前84,221,169件、メールアドレス106,266,766件、電話番号33,559,863件、平文パスワード20,185,831件、決済情報27,487,924件が含まれる
- 研究者らは13日間で842件の通報メールを送ったが、設定を修正したサイト所有者は24%、返信した割合は1%、バグバウンティを提案したのは2サイトにとどまった
インターネット規模のFirebase露出スキャン
- Chattr.aiの侵害事例 の後、誤って設定されたFirebaseインスタンスを通じて露出したPIIを探すためのインターネット全体スキャンが始まった
- 最初のPythonスキャナーは、Webサイトや読み込まれた
.jsバンドルからFirebase設定変数を確認していたが、約500スレッドで動作する中でメモリ使用量が増え、1時間以内にOOMが発生した - その後Goで書き直されたスキャナーは550万ドメインを対象に実行され、当初予想の約11日より長い2〜3週間を要した
- 初期の手作業レビューだけでも136サイトと620万レコードを見つけたが、候補リストが膨大になったため完全自動化が必要になった
Catalystと露出規模の算定
- Catalystは候補サイトやJavaScriptバンドルを入力として受け取り、一般的なFirebaseコレクションと、JavaScript内で直接言及されたコレクションの読み取りアクセス可否を自動確認する
- 読み取り可能なコレクションを見つけると、100件のレコードサンプルを収集して含まれる情報の種類を確認し、それをコレクション全体のサイズに掛けて影響を推定する
- 結果の保存先には、PostgreSQLベースのオープンソースFirebase競合製品であるSupabase が選ばれ、整理されたデータは非公開データベーステーブルにアップロードされた
- 集計値は次のとおりで、実際の露出規模は表示された数値より大きい可能性が残っている
- 全レコード: 124,605,664件
- 名前: 84,221,169件
- メールアドレス: 106,266,766件
- 電話番号: 33,559,863件
- パスワード: 20,185,831件
- 決済情報: 銀行情報、請求書など27,487,924件
影響が大きかったサイト
-
Silid LMS
- 学生と教師向けの学習管理システム
- 名前、メールアドレス、電話番号を含む2,700万人分のユーザーレコードが露出し、最大規模となった
-
オンライン賭博ネットワーク
- 相互にリスキンされた9つのサイトで構成される
- 一部のスピンは勝率が0%になるよう操作されていた
- 銀行口座の詳細なログイン情報が800万件と最も多く露出した
- 平文パスワードも1,000万件で、影響を受けたサイトの中で最大規模だった
- 問題を通報しようとする過程で、カスタマーサポートが会話中に言い寄ってきた
-
Lead Carrot
- コールドコール用のオンラインリード生成サービス
- 露出したユーザー情報の規模は上位3位で、2,200万人に影響がある
-
MyChefTool
- レストラン向けのビジネス管理アプリおよびPOSアプリケーション
- 露出した名前の数は1位、メールアドレスの数は2位で、それぞれ1,400万件と1,300万件が露出した
通報後の反応
- 研究者らは13日間で842件のメールを送信した
- 85%は配信され、9%は返送された
- サイト所有者の24%が誤設定を修正した
- 返信したサイト所有者は1%にとどまった
- 0.2%にあたる2つのサイト所有者がバグバウンティを提案した
1件のコメント
Hacker News の意見
Firebase で長く働いていたが、セキュリティルールの問題は製品をずっと悩ませてきた
自動で期限切れになるデフォルトルール、教育の強化など、さまざまなアプローチを試したが、結局いまだに安全でないデータベースが数多く見える
理由は複雑だが、Firebase 式のセキュリティルールはまだ馴染みの薄い概念で、既存の場所にデータを追加する新しい開発者が、そのデータのプライバシー要件の変化に合わせてルールまで直さないことが多い
また、それぞれが作ったバックエンドがもたらしていた「曖昧さによるセキュリティ」がなくなり、大規模スキャンが容易になった
特に Realtime Database のルールは書きにくく、スケーラビリティも良くないが、自動スキャンは通常、開かれたデータしか探さないので、
read write trueより少しマシなだけでも防げていた技術的に Firebase のアプローチ自体が間違っているわけではないが、保存データとセキュリティルール中心のモデルを使うほぼ唯一のバックエンドなので、誤解や誤用、こうした事故にさらされやすい
バックエンドでは検証・セキュリティルールが仕様の一部に見えるが、Firebase のセキュリティルールは別プロセスなので忘れられやすく、新機能を作るたびに再評価しなければならない
プロジェクト所有者に通知できる人の注意を引くには、Firebase 内部でかなり高い段階までエスカレーションする必要があったのだと思う
たとえば記事の「コンテンツ所有者のみアクセス」や「属性ベース・ロールベースアクセス」のようなテンプレートで、ほとんどのアプリのパターンをカバーできるのか、それとも本当にカスタムルールが多く必要なのか疑問だ
セキュリティルール作成の大きな問題は、ほぼすべてのミスがセキュリティ問題になるため、必要なければ触りたくないという点にある
ルールが厳しすぎるとアプリが動かないので直ちに分かるが、開きすぎている場合は過剰なアクセスを実際に試すまで表面化しにくい
関連して、各セキュリティルールごとにアクセス拒否の例示テストケースを開発者に書かせる方式も検討に値する
fireplanというルールトランスパイラがすべてのプロパティにデフォルトの"$other": {".read": false, ".write": false}ルールを追加するおかげで新しいフィールドは明示的に追加する必要があり、新しい値が既存ルールを知らないうちに「継承」することがほぼ不可能になった
Firebase を10年以上使ってきたので、最新のルールツールもこうしているのかは分からない
本当に役立つのは、制御しにくい複数のクライアントバージョンがある状況で、フィールド名変更やデータ構造変更を標準で支援すること、データベースを起動しなくてもルールを軽量にテストする方法、本番環境でルール失敗時により良いデバッグ情報を出すことだ
失敗するたびにルールがアクセスしたすべての値も一緒に記録しなければ、変化するデータによって生じる一時的な失敗をデバッグできない
これは十分に説明されていない概念モデルだ
プロジェクトでは各コレクションに、公開、ユーザーデータ、認証ユーザーのみ公開、管理者専用のようなセキュリティプロファイルがあるべきだと言い、コレクションごとにカスタム条件を書くのではなく、セキュリティルール関数でこうしたカテゴリを強制する形で取り組んでいる
フィールド単位ではなくコレクション単位でセキュリティを考えれば、1つのドキュメント内に異なるセキュリティ意図が混ざることを減らせる
コレクションが公開なら、公開でないフィールドを含めるべきではなく、必要なら Firestore トリガーでセンシティブなコンテキストから公開コンテキストへデータを複製できるが、逆方向はできない
問題は、ルール自体の外側でルールの意図を文書化しなければならないため誤適用しやすい点で、以前はテストを書くのも苦痛だったが、今はかなり改善されている
“How I pwned half of America’s fast food chains, simultaneously.”を思い出す: https://mrbruh.com/chattr/
HN: https://news.ycombinator.com/item?id=38933999
After the initial buzz of [pwning Chattr.ai] had settled down, […]私の見間違いでなければ、記事末尾の時点で、こうした脆弱性のあるサイトの**75%**がまだそのまま開いていて、ダンプ可能な状態という意味ではないのか?
とんでもないことだ
ある日には、コンピュータを触るには免許が必要だと思うこともある
ウェブサイトを作ってくれる制作会社に外注し、その制作会社は開発者を入れ替え続け、最初は優秀な開発者を付けるが、その後は会社が不満を言わない限り、より経験の浅い開発者に契約を任せる、という具合だ
脆弱性のメールはスパムとして無視されたか、転送された後に放置されたか、PM の会議予定キューに入り、クライアントにできるだけ請求しながら修正する項目になった可能性が高い
専門免許が義務の分野にも、無能な免許保持者は多い
医師も教育と免許要件は非常に厳しいが、ヤブ医者や免許を持つ代替医療従事者には事欠かない
各サイトに、影響を受けた内容、修正方法、連絡方法を盛り込んだカスタムメールを送り、最善を尽くした
これはPMの cheap-fast-good の三角形で安くて速い選択をした必然的な結果だと思う
残念ながら、一部の顧客やユーザーの懸念は議論から外され、彼らの個人情報がコストになった
ここに挙がっている企業のうち、そうした判断をしてもリーダーシップが変わっていないところには注意すると思う
多くの企業が顧客を守るほど十分に気を配っていないことは何度も証明されており、歴史は繰り返す
Firebaseについてごく基本的な質問がある:この記事のアプリの大半は、カスタムのサーバーコードなしで、静的ホスティングされたクライアント側JavaScriptだけで実装されていたのか?
バックエンドは100% GoogleがホスティングするFirebase設定という意味なのか気になる
もしそうなら、数百万人のユーザーがいるサイトでそのようなアーキテクチャがここまで一般的になっていたとは知らなかった
APIでデフォルト許可のセキュリティモデルを置くと、必然的にこうなる
残念ながら、JavaScript開発者向けのライブラリには安全でないデフォルト値がよくあり、GraphQLもこうした問題が出そうな領域に見える
Firebaseにはクラウドから呼び出せる関数であるFirebase Functionsもあり、そのコードは公開されない
ただしFirestoreやFirebase Realtime Databaseはいずれもユーザーがセキュリティルールを設定する必要があり、そうしなければ誰でも全データを読める
バックエンドで適切な認可ルールを簡単に書けるようにすることが重要だ
こういうのを見ると、ずいぶん前にパスワードマネージャーとバーチャルカードを選んでおいてよかったと感じる
それでもインターネットはさらに怖くなっている
ほとんどの人は、Webがどれほど脆弱で、自分たちがどれほど露出しているかをまったく知らない
AIエージェントがボットよりはるかに効率よく脆弱性を見つけるようになるだろうから、奇妙な未来が待っている感じがする
登録するサービスごとに固有のメールアドレスを使うべきだ
事故が起きたときに被害を限定でき、他のサービスと照合されて公開情報収集の対象になるのも防げる
ときどきその固有アドレス宛に悪意あるメールが来れば、サイト運営者より先に侵害に気づけることもある
「スレッドが約500個あるPythonプログラムは、時間が経つにつれてメモリを食い始める」という部分について、もっと知っている人はいる?
自分もPythonでスレッド数百個のスクレイパーを持っているが、かなりメモリを食っている気がする
回避策があるのか、それとも別の言語で書き直すのが唯一の解決策なのか気になる
個人的にはスレッドよりプロセスを好み、共有メモリよりワーカープールとメッセージバスを使う
この解決策にも欠点と多少のオーバーヘッドはあるが、メモリ問題をずっと気にしなくて済む
クローラーはプロセス数が比較的一定で、各プロセスの作業が独立しているため、プロセスモデルのほうが合っているように見える
import multiprocessing as threading書き直すのが、実質的にほぼ唯一の解決策だ
まさに非常によく合うユースケースだ
よくやった
影響を受けたユーザー数が実際にはもっと多い可能性が高い、という結論にどうやって至ったのか気になる
見たところ、ギャンブルサイトやLead Carrotのような一部サイトには偽のアカウントデータがかなり混ざっていた可能性もありそうだ
英語サイトでしかうまく機能しない方式だ
もっと多いと言った理由は、スキャン一覧になかった他のサービスも脆弱である可能性があるためだ