FixVibe

// docs / baas security / firebase if-true explainer

Firebase allow read, write: if true 解释:它做什么以及如何修复

<code>allow read, write: if true;</code> 是生产中最常见的单一 Firebase 配置错误。它是创建新数据库时 Firebase 控制台建议的测试模式默认值、AI 编码工具从文档重新生成的规则,以及向互联网上任何人开放整个 Firestore 数据库的规则。本文精确解释语法、展示此规则有效时攻击者看到的内容,并给出四个适合不同用例的逐步更严格替换。

逐行解释语法

一个完整的 Firestore 测试模式规则文档是六行:

firebase
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if true;
    }
  }
}

解码:

  • rules_version = '2'; 选择 v2 规则引擎 (当前)。较旧的 v1 规则已弃用。
  • service cloud.firestore 将块限定到 Firestore。Realtime Database 使用不同的基于 JSON 的语法;Cloud Storage 使用 service firebase.storage
  • match /databases/{database}/documents 绑定特殊的 (default) 数据库 (大多数项目只有一个)。
  • match /{document=**} 是递归通配符。** 匹配任意深度的任意路径。与 {document} 结合,这捕获每个集合中的每个文档 — 一个 match 子句统治整个数据库。
  • allow read, write: if true; 是规则主体。readwrite 都被允许;条件 if true 嘛,永远为真。read 涵盖 getlist 操作;write 涵盖 createupdatedelete

净效果:任何拥有 Firebase 项目 ID 和正确 SDK 的客户端都可以读取或写入任何集合中的任何文档。不需要身份验证。不强制速率限制。

Firebase 为何将此作为默认值

Firebase 希望你在创建项目后的前 30 秒内开始编码。替代方案 — 在任何读写工作之前让你编写正确的规则 — 会阻塞入门。所以控制台在你创建数据库时提供两个选项:生产模式 (拒绝一切,你自己写规则) 或测试模式 (30 天允许一切)。大多数开发者点击测试模式,然后忘了再去看。较旧的项目有 30 天计时器;当前项目有无自动过期的不确定 if true 规则。

结构性问题:AI 编码工具在显示测试模式规则的文档、教程和 Stack Overflow 答案上训练。当你问 Cursor 或 Claude Code「如何设置 Firebase」时,答案常常包含完全相同的 allow read, write: if true 块,仿佛它就是生产规则。AI 不知道 — 也没有被提示去知道 — 此规则对生产不安全。

攻击者看到什么

具体来说,知道你的 Firebase 项目 ID (可从任何已部署应用的包中 30 秒内提取) 并运行以下内容的攻击者,可以列出每个集合中的每个文档:

单个未认证 curl 请求就足以枚举每个集合。见下方高亮块。

bash
curl 'https://firestore.googleapis.com/v1/projects/[project-id]/databases/(default)/documents:listCollectionIds' \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{}'

响应是顶层集合的完整列表。对每个集合,第二个请求返回文档。此路径没有速率限制,因为 if true 规则接受匿名流量。我们见过在不到一小时内被枚举的拥有数百万文档的 Firebase 数据库。

在写入路径上:带 {fields} 的单次 POST 创建新文档。攻击者可以用垃圾污染你的集合,污损从 Firestore 读取的用户面页面,或将你的数据库用作免费消息代理 — 你的使用账单飙升,你调查,账单解释了问题。

四个生产安全替代方案

选择匹配你应用数据模型的替代方案。所有四种都假设你有用户身份验证 (Firebase Auth 或任何发行 Firebase ID 令牌的提供商):

选项 1:用户拥有的文档

最常见的 SaaS 模式。文档位于 /users/{userId}/... 下,只有所有者可以接触它们。match /users/{userId}/{document=**} { allow read, write: if request.auth != null && request.auth.uid == userId; }

firebase
match /users/{userId}/{document=**} {
  allow read, write: if request.auth != null
                     && request.auth.uid == userId;
}

选项 2:每个文档上的所有者字段

当文档位于扁平集合中 (未嵌套在用户 ID 下) 时,存储一个 owner_uid 字段并检查它。match /posts/{postId} { allow read: if resource.data.public == true || resource.data.owner_uid == request.auth.uid; allow write: if request.auth.uid == resource.data.owner_uid; }

firebase
match /posts/{postId} {
  allow read:  if resource.data.public == true
              || resource.data.owner_uid == request.auth.uid;
  allow write: if request.auth.uid == resource.data.owner_uid;
}

选项 3:多租户组织隔离

适用于具有组织范围数据的 B2B SaaS。在每个文档上存储 org_id 字段,并对照用户的自定义声明检查它。allow read, write: if request.auth.token.org_id == resource.data.org_id;。需要在注册期间通过 Firebase Admin SDK 设置自定义声明。

firebase
allow read, write: if request.auth.token.org_id == resource.data.org_id;

选项 4:只读公共内容

适用于营销内容、公共个人资料、产品目录 — 任何真正公开读取但仅管理员写入的内容。match /products/{productId} { allow read: if true; allow write: if request.auth.token.admin == true; }admin 自定义声明只在管理员账户上设置。

firebase
match /products/{productId} {
  allow read:  if true;
  allow write: if request.auth.token.admin == true;
}

快速审计查询

在修复前,检查 if true 是否真的生效。打开 Firebase 控制台 → Firestore → Rules 并搜索 if true。如果你在注释之外的任何地方找到它,就有一项开放规则发现。同一 UI 中的规则模拟器让你在本地重放攻击者的请求 — 粘贴一个匿名 GET /users/somebody 并确认模拟器返回 允许

外部确认:对你的生产 URL 运行 FixVibe 扫描。baas.firebase-rules 检查会探测你的 Firestore、Realtime Database 和 Storage 规则,并报告攻击者会发现的相同发现 — 独立于 Firebase 控制台显示的内容。

常见问题

<code>if true</code> 和 <code>if request.auth != null</code> 之间有什么区别?

if true 允许匿名访问 — 互联网上的任何人。if request.auth != null 需要任何登录用户,这更好但仍然错误:你应用的任何用户都能读取其他每个用户的数据。生产规则必须通过 request.auth.uid == resource.data.owner_uid 或类似方式限定到特定用户或组织。

Firebase 会自动让 <code>if true</code> 规则过期吗?

较旧项目 (2023 年前) 有 30 天计时器,会将 if true 规则转换为 if false。当前项目没有 — 规则会无限期存续,直到手动替换。如果你的项目在 2023 年前创建,规则看起来没问题,请仔细检查:计时器可能已将它们翻转为 if false,这会阻塞你自己的应用。

我可以使用未来日期时间戳检查作为安全网吗?

不能 — 时间戳条件不是安全控制。它在未来日期使开放规则过期,这意味着在那个日期之前攻击者拥有完全访问权。而你会忘记这个日期。用基于身份验证的规则替换 if true,而不是时间限制的规则。

如果我的应用真的是公开读取 (博客、产品目录) 怎么办?

那么明确地写 allow read: if true; allow write: if false; 仅在公共集合上 — 而不是数据库中的每个集合。每个集合使用单独的 match 子句,并且绝不在可写规则上使用递归 {document=**} 通配符。

后续步骤

对你的生产 URL 运行 FixVibe 扫描 — baas.firebase-rules 检查确认 if true 目前从公共互联网是否可利用。有关扫描器机制以及对 Realtime Database 和 Storage 的并行检测,请参阅 Firebase 规则扫描器。有关 Supabase 上的等效配置错误类别,请阅读 Supabase RLS 扫描器

// 扫描你的 baas 面

在其他人之前找到开放的表。

输入一个生产 URL。FixVibe 会列举你的应用通信的 BaaS 提供商,识别它们的公共端点,并报告未经身份验证的客户端可以读取或写入什么。免费,无需安装,无需信用卡。

  • 免费层 — 每月 3 次扫描,注册无需信用卡。
  • 被动 BaaS 指纹识别 — 无需域名所有权验证。
  • Supabase、Firebase、Clerk、Auth0、Appwrite 等。
  • 每项发现都附带 AI 修复提示 — 可粘贴回 Cursor / Claude Code。
Firebase allow read, write: if true 解释:它做什么以及如何修复 — Docs · FixVibe