РУКОВОДСТВО ПО БЕЗОПАСНОСТИ СЕРВЕРОВ

Правила безопасности Firebase: чек-лист Firestore и Storage

Коротко: правила безопасности Firebase (Security Rules) единственное, что мешает постороннему читать или менять данные вашего Firestore, Cloud Storage или Realtime Database прямо из браузера. Чтобы защитить приложение, замените тестовые правила и if true правилами «только владелец», проверяйте форму входящих данных, держите Admin SDK на сервере, ограничьте ключи API, включите App Check и проверьте каждое правило в эмуляторе до деплоя.

Firebase позволяет веб- или мобильному приложению обращаться к базе напрямую, без вашего сервера посередине. Поэтому приложения на Firebase, написанные в стиле вайб-кодинга, так часто остаются открытыми: всё работает, и в правила никто не заглядывает. Эта страница Firebase-часть чек-листа безопасности вайб-кодинга. Вайб-кодинг означает сборку приложения с помощью ИИ-ассистента и выпуск того, что он написал.

Быстрый результат (20 минут)

  • Откройте вкладку Rules у Firestore, Storage и Realtime Database и найдите if true, ".read": true или allow read, write;. Замените каждое. См. Шаг 1.
  • Если проект настроен через Firebase CLI, найдите файлы правил, указанные в firebase.json: деплой из CLI перезаписывает правила, отредактированные в консоли.
  • Проверьте, нет ли правила, где условие только request.auth != null. Тогда каждый вошедший пользователь видит всё.
  • В консоли Google Cloud откройте список ключей API и убедитесь, что браузерный ключ разрешает только API Firebase, а ключа Gemini или другого платного API нет во фронтенд-коде.
  • Откройте Rules Playground, выберите неавторизованный запрос и попробуйте прочитать закрытую коллекцию. Доступ должен быть отклонён.
Путь запроса Firebase: клиентский SDK, необязательный App Check, личность из входа, решение правил безопасности, доступ к данным или отказ
Каждый клиентский запрос проходит через правила; если ни одно совпавшее правило его не разрешает, Firebase отказывает.

Что такое правила безопасности Firebase и что они защищают

Правила безопасности Firebase (Firebase Security Rules) это условия на небольшом языке правил, которые Firebase проверяет на своих серверах до чтения или записи ваших данных. Согласно документации Firestore, каждый запрос из мобильной или веб-библиотеки сначала проверяется по правилам, и если правила запрещают хотя бы один из запрошенных путей документов, весь запрос завершается ошибкой. Та же система работает для Cloud Firestore, Cloud Storage for Firebase и Realtime Database, у каждого свои правила.

Главная мысль: код во фронтенде принадлежит посетителю. Он может открыть инструменты разработчика и отправить любой запрос, который ваше приложение могло бы отправить, или тот, который оно никогда бы не отправило. Скрытая кнопка или проверка в JavaScript не защита. Правила выполняются там, где посетитель не может их изменить.

Есть два важных исключения. Firebase документирует, что серверные клиентские библиотеки Firestore обходят все правила безопасности и аутентифицируются через Google Application Default Credentials. Для Realtime Database Admin SDK может работать с полными административными правами, то есть с полным доступом на чтение и запись. Поэтому Admin SDK и учётные данные сервисного аккаунта очень мощны и должны жить только на сервере под вашим контролем (см. безопасный деплой приложения на VPS), но не в приложении, которое скачивают посетители.

Шаг 1: Уберите тестовый режим и открытые правила

Когда вы создаёте базу или хранилище в консоли Firebase, вы выбираете стартовый режим. По быстрому старту Firestore, тестовый режим (test mode) подходит для начала работы с клиентскими библиотеками, но позволяет любому читать и перезаписывать ваши данные. Производственный режим (production mode) запрещает все чтения и записи из мобильных и веб-клиентов. Страница основ правил называет их Locked mode и Test mode. В Locked mode Firestore и Realtime Database закрыты для всех, а Cloud Storage пускает только аутентифицированных пользователей.

Тестовый режим рассчитан на первый вечер, а не на запуск. В просмотренных мной страницах документации срок действия по умолчанию не указан, поэтому на него не рассчитывайте: читайте собственные правила. Если вы видите условие с датой на основе request.time, это срок, который кто-то записал, и после этой даты запросы отклоняются. Не «чините» появившиеся ошибки доступа переносом даты или заменой на if true. Напишите нормальные правила.

Шаблон, который нужно искать, со страницы Firebase о небезопасных правилах:

// Firestore: НИКОГДА не используйте это в продакшене
match /{document=**} {
  allow read, write: if true;
}

Предупреждение Firebase прямое: никогда не используйте этот набор правил в продакшене, он позволяет любому перезаписать всю вашу базу. На странице добавлено, что любой, кто угадает ID вашего проекта, может украсть, изменить или удалить данные. Эквиваленты: ".read": true и ".write": true в Realtime Database и allow read, write; без условия в Cloud Storage.

  • Найдите открытый доступ во всех трёх файлах правил. Если вы управляете правилами через Firebase CLI, файлы указаны в firebase.json. Документация предупреждает, что деплой из CLI перезаписывает то, что лежит в консоли, поэтому редактируйте только один источник.
  • Доступ «любому вошедшему» тоже считайте открытым. Firebase относит request.auth != null (Storage), request.auth.uid != null (Firestore) и auth.uid !== null (Realtime Database) к не рекомендованным для закрытых данных: каждый вошедший пользователь получает доступ ко всему. Firebase Authentication поддерживает и анонимный вход, а Rules Playground позволяет проверить запрос от анонимного пользователя, поэтому простая проверка входа может быть слабее, чем вам кажется.
  • Не игнорируйте оповещение. Если вы получили сообщение, что ваша база Firestore защищена недостаточно, Firebase предлагает исправить это, изменив и протестировав правила, а не закрыв письмо.
  • Полностью закрытая база допустима. Правила, запрещающие всё, документированы как подходящие, если базой пользуется только сервер. Тогда проверьте, что клиенты по-прежнему получают нужные данные.

Шаг 2: Напишите правила «только владелец» для Firestore

Самый частый безопасный шаблон это доступ только для владельца контента: человек читает и меняет лишь те документы, которые создал. Для приложения заметок, где каждый документ хранит владельца в поле userId, документированные элементы Firebase дают такой результат. request.auth содержит личность вошедшего пользователя, resource.data поля уже сохранённого документа, а request.resource.data документ в том виде, какой он будет после записи.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /notes/{noteId} {
      // Читать и удалять можно только свои заметки
      allow read, delete: if request.auth != null
                          && request.auth.uid == resource.data.userId;

      // Создание: сохранённого документа ещё нет, проверяем входящие данные
      allow create: if request.auth != null
                    && request.auth.uid == request.resource.data.userId;

      // Обновление: заметка уже ваша, и передать её другому нельзя
      allow update: if request.auth != null
                    && request.auth.uid == resource.data.userId
                    && request.resource.data.userId == resource.data.userId;
    }
  }
}

Почему create отдельно: у нового документа ничего не сохранено, поэтому правилу с resource.data.userId не с чем сравнивать. Firebase описывает create как применимое к записи в несуществующие документы, поэтому проверка использует request.resource.data. Правило обновления повторяет шаблон Firebase «владелец сохраняется при обновлении»: и старый, и новый владелец должны быть текущим пользователем.

  • Помните, что правила не фильтры. Firebase указывает, что сам запрос должен содержать ограничения, гарантирующие, что каждый результат проходит правило. Для заметок выше запрашивайте с where("userId", "==", uid), иначе весь запрос будет отклонён.
  • Правила не наследуются подколлекциями. Правила применяются только к совпавшему пути, поэтому подколлекции нужен свой блок match.
  • Следите за пересекающимися match. Если одному документу соответствуют несколько правил allow, доступ разрешён, когда истинно любое условие. Один забытый общий match /{document=**} с if true сводит на нет всё остальное.
  • Разделяйте публичное и закрытое сознательно. Firebase документирует смешанный шаблон: публичное чтение allow read: if true для контента, который должен быть публичным, и запись только для владельца. Никогда не применяйте его к коллекции с личными данными.

Если вы вместо этого используете Postgres через Supabase, та же идея называется защитой на уровне строк (row-level security) и имеет собственный чек-лист.

Открытые правила Firestore, где читать и писать может любой, в сравнении с правилами владельца, проверяющими вход и userId
Одна коллекция заметок: с открытыми правилами и с правилами, привязывающими каждый документ к владельцу.

Шаг 3: Проверяйте форму входящих данных

Владение определяет, кто может писать. Валидация данных определяет, что именно можно писать. Firebase документирует, что правила могут ограничивать запись по новым данным через request.resource.data. Два документированных примера, полезных для коллекции заметок или профилей:

// Запретить документы с полем, которое пользователь не должен задавать
allow create: if !("ranking" in request.resource.data);

// Требовать положительное число и неизменное имя при обновлении
allow update: if request.resource.data.population > 0
              && request.resource.data.name == resource.data.name;

Примените ту же идею ко всему, что атакующий хотел бы выставить в собственной записи: поле isAdmin или role, цену, баланс, флаг approved. Если клиент никогда не должен это писать, правило должно отклонять запись, содержащую это поле. Ещё лучше хранить такие значения в коллекции, в которую может писать только ваш сервер.

  • Составьте список полей, которые пользователь может писать, и отклоняйте записи с другими.
  • Не держите роли и деньги в документах, доступных пользователю на запись. Firebase документирует ролевой доступ через поиск документа пользователя с помощью get(). Сам документ с ролью не должен быть доступен на запись тому, кого он описывает.
  • Просите ИИ-ассистента объяснять каждое правило простыми словами и проверяйте его слова инструментами из Шага 8. Правила ассистента не лучше его промпта. См. правила безопасности для ИИ-ассистентов.

Шаг 4: Закройте файлы в Cloud Storage

У Cloud Storage for Firebase свои правила, отдельные от Firestore. По документации правил Storage, правила по умолчанию требуют Firebase Authentication для любого чтения или записи, а у неаутентифицированного запроса request.auth равен null. Это лучше, чем открытый доступ, но каждый вошедший пользователь всё равно может трогать любые файлы. Привяжите каждый путь к владельцу и добавьте ограничения по размеру и типу, как в примерах Firebase про пользовательскую безопасность и валидацию данных:

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/{fileName} {
      allow read: if request.auth != null
                  && request.auth.uid == userId;

      // Только изображения до 5 МБ (размер в байтах)
      allow create, update: if request.auth != null
                            && request.auth.uid == userId
                            && request.resource.size < 5 * 1024 * 1024
                            && request.resource.contentType.matches('image/.*');

      allow delete: if request.auth != null
                    && request.auth.uid == userId;
    }
  }
}
  • Кладите файлы в путь отдельного пользователя, например users/{userId}/..., чтобы правило могло сравнить путь с request.auth.uid.
  • Ограничивайте размер и тип содержимого через request.resource.size и request.resource.contentType. Без этого один пользователь может забить хранилище огромными файлами, а это ещё и ваши деньги.
  • Разделяйте write на create, update и delete, когда условия различаются. Firebase документирует эти детальные операции для Storage, а read делится на get и list в версии правил 2.
  • Помните правило ИЛИ. Если файлу соответствует несколько match, запрос разрешён, когда проходит любое правило. Широкое правило /{allPaths=**} может отменить аккуратные.

Нужен второй взгляд на ваш сервер?

Если ваше приложение на Firebase обращается ещё и к бэкенду на VPS, бесплатная проверка в режиме только чтения покажет, что открыто на сервере и что исправлять в первую очередь.

Получить бесплатную проверку сервера Связаться с инженером по безопасности

Шаг 5: Каскад правил Realtime Database

Если вы используете Realtime Database, её правила это JSON, и работают они иначе, чем в Firestore. Страница основного синтаксиса объясняет, что правила .read и .write каскадируются: если правило даёт доступ по пути, оно даёт доступ и ко всем дочерним узлам, а более глубокое правило не может этот доступ отобрать. В их примере на /foo задано условие .read, а на /foo/bar стоит .read: false, и второе правило игнорируется, потому что чтение уже разрешено.

Практическое правило: давайте мало наверху и добавляйте доступ на более глубоких путях, но не наоборот. Один ".read": true в корне делает все правила ниже неважными. Раскладка «только владелец» выглядит так:

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "auth.uid === $uid",
        ".write": "auth.uid === $uid"
      }
    }
  }
}
  • Держите корень закрытым: никаких .read или .write на верхнем уровне, если вся база действительно не публична.
  • Правила и здесь не фильтры. Правила применяются атомарно: чтение родительского пути полностью проваливается, если ни одно правило на этом пути или выше не даёт доступ, даже если часть дочерних узлов читаема.
  • Используйте .validate для структуры и формата и помните, что все правила validate должны выполняться на каждом уровне.

Шаг 6: Какие ключи Firebase секретны

Вайб-кодеры часто пугаются, увидев apiKey во фронтенд-коде, или игнорируют настоящий секрет, лежащий рядом. Страница Firebase про ключи API для Firebase всё расставляет по местам. Ключи API для сервисов Firebase лишь идентифицируют ваш проект и приложение. Они не управляют доступом к данным: это делают правила безопасности (какие пользователи) и App Check (какие приложения). Firebase пишет, что ограниченные ключи Firebase не нужно считать секретами и их безопасно держать в коде или в закоммиченных конфигах, если вы следуете его рекомендациям.

У этого утверждения есть условия, и они составляют чек-лист:

  • Браузерный ключ Firebase только для Firebase. В консоли Google Cloud в его ограничениях API должны быть только API, связанные с Firebase. Firebase предупреждает, что при выборе «Don't restrict key» ключ может обращаться к любому API, включённому в проекте.
  • Для любого другого API Google используйте отдельный ограниченный ключ. Никогда не добавляйте Gemini Developer API в список разрешённых для публичного ключа. Firebase пишет, что ключ Gemini Developer API ни в коем случае нельзя включать в код или конфигурационные файлы.
  • Ужесточите квоту на вход, если используете вход по паролю. Найденный посторонним ключ не даёт читать данные, защищённые правилами, но с ним можно обращаться к эндпоинтам Authentication. Firebase советует снизить квоту по умолчанию для эндпоинтов identitytoolkit.googleapis.com до нормального трафика, чтобы затруднить подбор паролей.
  • Файл JSON сервисного аккаунта это настоящий секрет. Страница настройки Admin SDK предлагает сгенерировать файл закрытого ключа в формате JSON и надёжно его хранить. У владельца этого файла серверная власть над проектом, а серверные библиотеки Firestore вообще обходят правила.

На сервере передавайте Admin SDK учётные данные через переменную окружения, которую называет документация, и держите файл вне репозитория и читаемым только для пользователя приложения:

export GOOGLE_APPLICATION_CREDENTIALS="/etc/myapp/service-account.json"
chmod 600 /etc/myapp/service-account.json

Первая строка сообщает Admin SDK, где лежит файл. Вторая делает его доступным только владельцу. Никогда не коммитьте этот файл; см. управление секретами, переменные окружения и открытые файлы .env и .git. Если ключ сервисного аккаунта или ключ Gemini всё же утёк, действуйте по инструкции что делать при утечке ключа API: отзовите и замените ключ, а не просто удаляйте файл.

Шаг 7: Включите App Check и оповещения о расходах

App Check это сервис Firebase, который проверяет, что запрос пришёл из вашего настоящего приложения на настоящем устройстве, ещё до того, как он дойдёт до бэкенда. Документация App Check сообщает, что он работает с Cloud Firestore, Realtime Database, Cloud Storage for Firebase, вызываемыми Cloud Functions, Firebase AI Logic и другими сервисами. После включения принудительной проверки (enforcement) запросы без действительной аттестации отклоняются. В вебе используется reCAPTCHA Enterprise, на платформах Apple и Android поддерживаются провайдеры вроде App Attest и Play Integrity.

Трезво оценивайте его возможности. Firebase пишет, что App Check предотвращает часть, но не все векторы злоупотреблений, и не гарантирует устранение любых злоупотреблений. Он дополняет Authentication и правила, а не заменяет их: Authentication говорит, кто пользователь, App Check говорит, что вызов пришёл из вашего приложения. Он защищает от скриптов, которые пользуются вашим проектом без вашего приложения. Та же забота стоит за ограничением частоты запросов и защитой от DDoS. Первое время смотрите вкладку Usage каждого продукта ежедневно, а о привычке читайте в статье мониторинг сервера и анализ логов.

  • Включите App Check для используемых продуктов Firebase и перед принудительной проверкой посмотрите метрики запросов, чтобы не заблокировать собственных настоящих пользователей.
  • Настройте оповещение о бюджете. По рекомендациям Firebase по биллингу, бюджеты только с оповещениями шлют письма при достижении порогов, но не приостанавливают сервисы. Лимиты расходов, которые приостанавливают сервис, существуют лишь для нескольких продуктов (Firebase AI Logic, App Hosting, Cloud Functions for Firebase и Extensions), но не для Firestore или Storage. При переходе на тариф Blaze вам предлагают создать бюджет с оповещениями.
  • Ограничивайте запросы. Firebase называет частой причиной неожиданных расходов забытый лимит в запросе, который возвращает миллионы документов.

Шаг 8: Проверьте правила до деплоя

Правила это код, а непроверенные правила это догадки. Firebase даёт два инструмента. Быстрый это Rules Playground в консоли: по документации он позволяет проверить чтение или запись по пути от имени неаутентифицированного, анонимного или конкретного пользователя. Для более тщательной проверки сам Firebase рекомендует локальный эмулятор. Установите его и запустите эмулятор Firestore через Firebase CLI:

firebase setup:emulators:firestore
firebase emulators:start --only firestore
Терминал с командами Firebase CLI: установка и запуск эмулятора Firestore, затем деплой правил Firestore и Storage
Установите и запустите эмулятор, прогоните тесты правил и только потом деплойте правила.

Первая команда загружает эмулятор. Вторая запускает его на вашей машине, поэтому тесты не трогают рабочие данные. Ловушка из документации: если не указать эмулятору файл правил (поле firestore.rules в firebase.json), он считает правила всех проектов открытыми, и «зелёный» тест может ничего не значить.

Для повторяемых тестов Firebase поставляет библиотеку @firebase/rules-unit-testing. Она умеет изображать вошедшего и невошедшего пользователя, и Firebase отмечает, что она всегда работает с эмуляторами и никогда не касается продакшена. Набросок на правилах заметок из Шага 2:

const alice = testEnv.authenticatedContext('alice');
const bob = testEnv.authenticatedContext('bob');

// Alice может создать свою заметку
await assertSucceeds(setDoc(doc(alice.firestore(), 'notes/n1'),
  { userId: 'alice', title: 'hello' }));

// Bob не может её прочитать, и невошедший посетитель тоже
await assertFails(getDoc(doc(bob.firestore(), 'notes/n1')));
await assertFails(getDoc(doc(testEnv.unauthenticatedContext().firestore(), 'notes/n1')));

Всегда добавляйте негативные тесты: другой пользователь, невошедший посетитель, запись с добавленным полем isAdmin, загрузка в Storage сверх лимита размера. Деплойте только когда они проходят. Firebase документирует такие команды CLI для деплоя, по одной на продукт:

firebase deploy --only firestore:rules
firebase deploy --only database
firebase deploy --only storage

После деплоя повторите проверку, которую сделал бы атакующий: откройте приложение без входа, затем войдите вторым тестовым пользователем и попробуйте прочитать данные первого. Если что-то не так и вы подозреваете, что данные уже скопировали, переходите к реагированию на взлом: сначала закройте правила, потом смените ключи. Если нужен второй взгляд на серверную часть вашего стека, сравните управляемую безопасность и самостоятельную защиту.

Весь чек-лист на одном экране

  • Нигде нет if true, ".read": true или allow read, write; без условия.
  • Нет правил «просто вошёл» для закрытых данных.
  • Тестовый режим заменён; в файле не осталось забытого срока на request.time.
  • Firestore: проверка владельца при чтении, создании (через request.resource.data), обновлении и удалении.
  • Пользователь не может записать роль, цену или флаг администратора в свой документ.
  • Storage: пути по пользователям, лимиты размера и типа, нет общего match.
  • Realtime Database: корень закрыт, доступ добавлен глубже, есть .validate.
  • Браузерный ключ Firebase ограничен API Firebase; ключей Gemini и других платных API нет во фронтенде.
  • JSON сервисного аккаунта и Admin SDK только на сервере и вне Git.
  • App Check включён; оповещения о бюджете настроены; у запросов есть лимиты.
  • Правила проверены в эмуляторе негативными тестами и задеплоены из одного источника.

Ещё для вайб-кодеров: все руководства серии собраны в центре безопасности для вайб-кодеров, а пункты можно отмечать в интерактивном чек-листе.

Часто задаваемые вопросы

Что такое правила безопасности Firebase?

Это условия, которые Firebase проверяет на своих серверах до того, как клиентское приложение прочитает или запишет данные в Firestore, Cloud Storage или Realtime Database. Проверяется каждый запрос из веб- или мобильной библиотеки, и если правила его запрещают, он завершается ошибкой. Они заменяют проверки доступа, которые иначе пришлось бы писать на собственном сервере.

Безопасно ли оставлять тестовый режим Firebase?

Нет. Firebase описывает тестовый режим как удобный для начала работы, но позволяющий любому читать и перезаписывать ваши данные. Используйте его только с временными данными, а до публикации приложения замените правилами, которые проверяют request.auth и владельца.

Почему приложение Firebase вдруг пишет permission denied?

Частая причина: в правилах есть условие с датой на основе request.time, и эта дата прошла. В просмотренных мной страницах документации срок тестового режима по умолчанию не указан, поэтому прочитайте даты в своём файле правил. Исправляйте нормальными правилами по владельцу, а не переносом даты или if true.

Является ли ключ API Firebase секретом?

Не так, как серверный ключ. Firebase пишет, что ключи API для сервисов Firebase только идентифицируют проект, а доступом управляют правила безопасности и App Check, поэтому ограниченные ключи Firebase можно держать в коде. Файлы JSON сервисного аккаунта, учётные данные Admin SDK и любой ключ Gemini Developer API секретны и не должны попадать во фронтенд.

Что делает allow read, write: if true?

Оно разрешает любому в интернете, кто знает ID вашего проекта, читать, менять и удалять всё, что подпадает под этот match. Firebase требует никогда не использовать это в продакшене. Замените правилом, которое проверяет request.auth и то, что документ принадлежит пользователю.

Действуют ли правила безопасности на Admin SDK?

Нет. Firebase документирует, что серверные клиентские библиотеки Firestore обходят все правила безопасности и используют Google Application Default Credentials, а Admin SDK для Realtime Database может иметь полный доступ на чтение и запись. Держите такой код и его учётные данные только на своём сервере.

Как проверить правила Firebase без деплоя?

Используйте Firebase Local Emulator Suite с библиотекой для модульных тестов правил: она имитирует вошедших и невошедших пользователей и никогда не касается продакшена. Для быстрой ручной проверки Rules Playground в консоли позволяет проверить чтение или запись от имени неаутентифицированного, анонимного или конкретного пользователя.

Не уверены, в каком состоянии ваш сервер?

Получите бесплатную проверку безопасности в режиме только чтения или поговорите с инженером по безопасности об управляемой защите.

Получить бесплатную проверку сервера Связаться с инженером по безопасности