Usa esta guía para comprender las vulnerabilidades comunes en los parámetros de configuración de Firebase Security Rules, revisar y proteger mejor tus propias reglas, y probar los cambios antes de implementarlos.
Si recibes una alerta que indica que tus datos no están protegidos adecuadamente, revisa estos errores comunes y actualiza las reglas vulnerables.
Accede a tu Firebase Security Rules
Para ver tu Rules existente, usa la CLI de Firebase o la consola de Firebase. Asegúrate de editar tus reglas con el mismo método, de manera consistente, para evitar reemplazar las actualizaciones por error. Si no estás seguro de si tus reglas definidas de forma local reflejan las actualizaciones más recientes, la consola de Firebase siempre muestra la versión implementada más recientemente de tus reglas de seguridad de Firebase Security Rules.
Para acceder a tus reglas desde la consola de Firebase, selecciona tu proyecto y, luego, navega a Realtime Database, Cloud Firestore o Storage. Haz clic en Reglas una vez que estés en la base de datos o el bucket de almacenamiento correcto.
Para acceder a tus reglas desde la CLI de Firebase CLI, dirígete al archivo de reglas anotado en el archivo firebase.json.
Comprende Firebase Security Rules
Firebase Security Rules protege tus datos de usuarios maliciosos. Cuando creas una instancia de base de datos o un bucket de Cloud Storage en la consola de Firebase, puedes elegir si quieres denegar el acceso a todos los usuarios (Modo bloqueado) o otorgarles acceso a todos (Modo de prueba). Aunque se recomienda que tengas una configuración más abierta durante el desarrollo, tómate el tiempo para configurar correctamente las reglas y proteger los datos antes de implementar tu app.
Usa uno de los emuladores locales de Firebase para ejecutar tu app en un entorno de desarrollo local a medida que la desarrollas y pruebas diferentes configuraciones en tus reglas.
Situaciones comunes con reglas inseguras
Debes revisar y actualizar las Rules que configuraste de forma predeterminada o mientras trabajaste en el desarrollo de tu app antes de implementarla. Evita los siguientes errores comunes para asegúrate de proteger los datos de los usuarios.
Acceso abierto
Durante la configuración de tu proyecto de Firebase, es posible que hayas establecido reglas para permitir el acceso abierto durante el desarrollo. Tal vez creas que eres el único usuario de tu app, pero, si la implementaste, ya está disponible en Internet. Si no autenticas a los usuarios ni configuras las reglas de seguridad, cualquier persona que adivine el ID del proyecto podrá robar, modificar o borrar los datos.
No se recomienda: Otorgar acceso de lectura y escritura para todos los usuarios.// Allow read/write access to all users under any conditions // Warning: **NEVER** use this ruleset in production; it allows // anyone to overwrite your entire database. service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if true; } } } { // Allow read/write access to all users under any conditions // Warning: **NEVER** use this ruleset in production; it allows // anyone to overwrite your entire database. "rules": { ".read": true, ".write": true } } // Anyone can read or write to the bucket, even non-users of your app. // Because it is shared with App Engine, this will also make // files uploaded using App Engine public. // Warning: This rule makes every file in your Cloud Storage bucket accessible to any user. // Apply caution before using it in production, since it means anyone // can overwrite all your files. service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow read, write; } } } |
Solución: Configurar reglas que restrinjan el acceso de lectura y escritura.
Define reglas que tengan sentido en tu jerarquía de datos. Una de las soluciones comunes a este problema es la seguridad basada en los usuarios con Firebase Authentication. Obtén más información sobre cómo autenticar usuarios mediante reglas. Solo para el propietario del contenidoservice cloud.firestore { match /databases/{database}/documents { // Allow only authenticated content owners access match /some_collection/{document} { // Allow reads and deletion if the current user owns the existing document allow read, delete: if request.auth.uid == resource.data.author_uid; // Allow creation if the current user owns the new document allow create: if request.auth.uid == request.resource.data.author_uid; // Allow updates by the owner, and prevent change of ownership allow update: if request.auth.uid == request.resource.data.author_uid && request.auth.uid == resource.data.author_uid; } } } Acceso público y privado mixtoservice cloud.firestore { match /databases/{database}/documents { // Allow public read access, but only content owners can write match /some_collection/{document} { // Allow public reads allow read: if true // Allow creation if the current user owns the new document allow create: if request.auth.uid == request.resource.data.author_uid; // Allow updates by the owner, and prevent change of ownership allow update: if request.auth.uid == request.resource.data.author_uid && request.auth.uid == resource.data.author_uid; // Allow deletion if the current user owns the existing document allow delete: if request.auth.uid == resource.data.author_uid; } } } Solo para el propietario del contenido{ "rules": { "some_path": { "$uid": { // Allow only authenticated content owners access to their data ".read": "auth !== null && auth.uid === $uid", ".write": "auth !== null && auth.uid === $uid" } } } } Acceso público y privado mixto{ // Allow anyone to read data, but only authenticated content owners can // make changes to their data "rules": { "some_path/$uid": { ".read": true, // or ".read": "auth.uid !== null" for only authenticated users ".write": "auth.uid === $uid" } } } Solo para el propietario del contenido// Grants a user access to a node matching their user ID service firebase.storage { match /b/{bucket}/o { // Files look like: "user/<UID>/file.txt" match /user/{userId}/{fileName} { allow read, write: if request.auth.uid == userId; } } } Acceso público y privado mixtoservice firebase.storage { match /b/{bucket}/o { // Files look like: "user/<UID>/file.txt" match /user/{userId}/{fileName} { allow read; allow write: if request.auth.uid == userId; } } } |
Acceso para cualquier usuario autenticado
En ocasiones, Rules verifican que el usuario acceda a su cuenta, pero no restringen el acceso según esa autenticación. Si una de las reglas incluye auth != null
, confirma que quieres que cualquier usuario autenticado tenga acceso a los datos.
Qué debes evitar: Permitir que cualquier usuario autenticado tenga acceso de lectura y escritura a toda tu base de datosservice cloud.firestore { match /databases/{database}/documents { match /some_collection/{document} { allow read, write: if request.auth.uid != null; } } } { "rules": { ".read": "auth.uid !== null", ".write": "auth.uid !== null" } } // Only authenticated users can read or write to the bucket service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow read, write: if request.auth != null; } } } |
Solución: Limitar el acceso mediante condiciones de seguridad.
Cuando verifiques la autenticación, te recomendamos usar una de las propiedades de autenticación para restringir aún más el acceso de algunos usuarios a conjuntos de datos específicos. Obtén más información sobre las diferentes propiedades de autenticación. Acceso según el rolservice cloud.firestore { match /databases/{database}/documents { // Assign roles to all users and refine access based on user roles match /some_collection/{document} { allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Reader" allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Writer" // Note: Checking for roles in your database using `get` (as in the code // above) or `exists` carry standard charges for read operations. } } } Acceso según los atributos// Give each user in your database a particular attribute // and set it to true/false // Then, use that attribute to grant access to subsets of data // For example, an "administrator" attribute set // to "true" grants write access to data service cloud.firestore { match /databases/{database}/documents { match /some_collection/{document} { allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true; allow read: true; } } } Acceso público y privado mixtoservice cloud.firestore { match /databases/{database}/documents { // Allow public read access, but only content owners can write match /some_collection/{document} { allow read: if true allow write: if request.auth.uid == request.resource.data.author_uid } } } Solo para el propietario del contenido{ "rules": { "some_path": { "$uid": { // Allow only authenticated content owners access to their data ".read": "auth.uid === $uid", ".write": "auth.uid === $uid" } } } } Acceso con una ruta trazada{ "rules": { "some_path/$uid": { ".write": "auth.uid === $uid", // Create a "public" subpath in your dataset "public": { ".read": true // or ".read": "auth.uid !== null" }, // Create a "private" subpath in your dataset "private": { ".read": "auth.uid === $uid" } } } } Acceso público y privado mixto{ // Allow anyone to read data, but only authenticated content owners can // make changes to their data "rules": { "some_path/$uid": { ".read": true, // or ".read": "auth.uid !== null" for only authenticated users ".write": "auth.uid === $uid" } } } Acceso grupal// Allow reads if the group ID in your token matches the file metadata `owner` property // Allow writes if the group ID is in the user's custom token match /files/{groupId}/{fileName} { allow read: if resource.metadata.owner == request.auth.token.groupId; allow write: if request.auth.token.groupId == groupId; } Solo para el propietario del contenido// Grants a user access to a node matching their user ID service firebase.storage { match /b/{bucket}/o { // Files look like: "user/<UID>/file.txt" match /user/{userId}/{fileName} { allow read, write: if request.auth.uid == userId; } } } Acceso público y privado mixtoservice firebase.storage { match /b/{bucket}/o { // Files look like: "user/<UID>/file.txt" match /user/{userId}/{fileName} { allow read; allow write: if request.auth.uid == userId; } } } |
(Realtime Database) Reglas heredadas de forma inadecuada
Realtime Database Security Rules en cascada, con reglas en rutas de acceso superiores y más superficiales que anulan las de los nodos secundarios más profundos. Cuando escribes una regla en un nodo secundario, recuerda que solo puede otorgar privilegios adicionales. No puedes definir mejor o revocar el acceso a los datos en una ruta de acceso más profunda en la base de datos.
No se recomienda: Definir mejor las reglas en rutas de acceso secundarias
{ "rules": { "foo": { // allows read to /foo/* ".read": "data.child('baz').val() === true", "bar": { /* ignored, since read was allowed already */ ".read": false } } } } |
Solución: Escribir reglas en rutas de acceso superiores que sean amplias y otorgar privilegios más específicos en rutas de acceso secundarias. Si las necesidades de acceso a tus datos requieren un mayor nivel de detalle, aplícalo en tus reglas. Obtén más información sobre la aplicación en cascada de Realtime Database Security Rules en la sintaxis básica de Realtime Database Security Rules. |
Acceso cerrado
Otro enfoque común que puedes aplicar mientras desarrollas la app es mantener los datos bloqueados. Por lo general, esto significa que bloqueaste el acceso de lectura y escritura para todos los usuarios de la siguiente manera:
// Deny read/write access to all users under any conditions service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if false; } } }
{ "rules": { ".read": false, ".write": false } }
// Access to files through Cloud Storage is completely disallowed. // Files may still be accessible through App Engine or Google Cloud Storage APIs. service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow read, write: if false; } } }
Los SDK de Firebase Admin y Cloud Functions aún podrán acceder a tu base de datos. Usa estas reglas cuando quieras usar Cloud Firestore o Realtime Database como backend solo de servidor junto con el SDK de Firebase Admin. Aunque esta alternativa es segura, recomendamos que pruebes que los clientes de tu app puedan recuperar datos sin problemas.
Obtén más información sobre Cloud Firestore Security Rules y cómo funcionan en Comienza a usar Cloud Firestore Security Rules.
Prueba tu implementación de Cloud Firestore Security Rules
Para verificar el comportamiento de tu app y la configuración de Cloud Firestore Security Rules, usa el emulador de Firebase. Usa el emulador de Cloud Firestore para ejecutar y automatizar las pruebas de unidades en un entorno local antes de implementar las modificaciones.
Para validar rápidamente Firebase Security Rules en la consola de Firebase, usa el simulador de reglas de Firebase.