# GCP - Storage Privesc

{{#include ../../../banners/hacktricks-training.md}}

## Stockage

Informations de base :

{{#ref}}
../gcp-services/gcp-storage-enum.md
{{#endref}}

### `storage.objects.get`

Cette permission vous permet de **télécharger des fichiers stockés dans Cloud Storage**. Cela peut potentiellement vous permettre d'escalader des privilèges car dans certaines occasions **des informations sensibles y sont enregistrées**. De plus, certains services GCP stockent leurs informations dans des buckets :

- **GCP Composer** : Lorsque vous créez un environnement Composer, le **code de tous les DAGs** sera enregistré dans un **bucket**. Ces tâches peuvent contenir des informations intéressantes dans leur code.
- **GCR (Container Registry)** : L'**image** des conteneurs est stockée dans des **buckets**, ce qui signifie que si vous pouvez lire les buckets, vous pourrez télécharger les images et **rechercher des fuites et/ou du code source**.

### `storage.objects.setIamPolicy`

Vous pouvez vous donner la permission de **profiter de n'importe quel des scénarios précédents de cette section**.

### **`storage.buckets.setIamPolicy`**

Pour un exemple sur la façon de modifier les permissions avec cette permission, consultez cette page :

{{#ref}}
../gcp-unauthenticated-enum-and-access/gcp-storage-unauthenticated-enum/gcp-public-buckets-privilege-escalation.md
{{#endref}}

### `storage.hmacKeys.create`

La fonctionnalité "d'interopérabilité" de Cloud Storage, conçue pour des **interactions inter-cloud** comme avec AWS S3, implique la **création de clés HMAC pour les comptes de service et les utilisateurs**. Un attaquant peut exploiter cela en **générant une clé HMAC pour un compte de service avec des privilèges élevés**, permettant ainsi **d'escalader des privilèges au sein de Cloud Storage**. Bien que les clés HMAC associées aux utilisateurs ne soient récupérables que via la console web, les clés d'accès et secrètes restent **perpétuellement accessibles**, permettant un accès de sauvegarde potentiel. En revanche, les clés HMAC liées aux comptes de service sont accessibles via l'API, mais leurs clés d'accès et secrètes ne sont pas récupérables après leur création, ajoutant une couche de complexité pour un accès continu.
```bash
# Create key
gsutil hmac create <sa-email> # You might need to execute this inside a VM instance

## If you have TROUBLES creating the HMAC key this was you can also do it contacting the API directly:
PROJECT_ID = '$PROJECT_ID'
TARGET_SERVICE_ACCOUNT = f"exam-storage-sa-read-flag-3@{PROJECT_ID}.iam.gserviceaccount.com"
ACCESS_TOKEN = "$CLOUDSDK_AUTH_ACCESS_TOKEN"
import requests
import json
key = requests.post(
f'https://www.googleapis.com/storage/v1/projects/{PROJECT_ID}/hmacKeys',
params={'access_token': ACCESS_TOKEN, 'serviceAccountEmail': TARGET_SERVICE_ACCOUNT}
).json()
#print(json.dumps(key, indent=4))
print(f'ID: {key["metadata"]["accessId"]}')
print(f'Secret: {key["secret"]}')


# Configure gsutil to use the HMAC key
gcloud config set pass_credentials_to_gsutil false
gsutil config -a

# Use it
gsutil ls gs://[BUCKET_NAME]

# Restore
gcloud config set pass_credentials_to_gsutil true
```
Un autre script d'exploitation pour cette méthode peut être trouvé [ici](https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/storage.hmacKeys.create.py).

## `storage.objects.create`, `storage.objects.delete` = Permissions d'écriture dans le stockage

Pour **créer un nouvel objet** à l'intérieur d'un bucket, vous avez besoin de `storage.objects.create` et, selon [la documentation](https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions), vous avez également besoin de `storage.objects.delete` pour **modifier** un objet existant.

Une **exploitation très courante** des buckets où vous pouvez écrire dans le cloud est le cas où le **bucket sauvegarde des fichiers de serveur web**, vous pourriez être en mesure de **stocker un nouveau code** qui sera utilisé par l'application web.

### Composer

**Composer** est **Apache Airflow** géré à l'intérieur de GCP. Il a plusieurs fonctionnalités intéressantes :

- Il fonctionne à l'intérieur d'un **cluster GKE**, donc le **SA utilisé par le cluster est accessible** par le code s'exécutant à l'intérieur de Composer.
- Tous les composants d'un environnement de composer (**code des DAGs**, plugins et données) sont stockés à l'intérieur d'un bucket GCP. Si l'attaquant a des permissions de lecture et d'écriture sur celui-ci, il pourrait surveiller le bucket et **chaque fois qu'un DAG est créé ou mis à jour, soumettre une version compromise** afin que l'environnement de composer récupère la version compromise depuis le stockage.

**Vous pouvez trouver un PoC de cette attaque dans le dépôt :** [**https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs**](https://github.com/carlospolop/Monitor-Backdoor-Composer-DAGs)

### Cloud Functions

- Le code des Cloud Functions est stocké dans Storage et chaque fois qu'une nouvelle version est créée, le code est poussé vers le bucket et ensuite le nouveau conteneur est construit à partir de ce code. Par conséquent, **écraser le code avant que la nouvelle version ne soit construite permet d'exécuter du code arbitraire dans la fonction cloud**.

**Vous pouvez trouver un PoC de cette attaque dans le dépôt :** [**https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions**](https://github.com/carlospolop/Monitor-Backdoor-Cloud-Functions)

### App Engine

Les versions d'AppEngine génèrent des données à l'intérieur d'un bucket avec le format de nom : `staging.<project-id>.appspot.com`. À l'intérieur de ce bucket, il est possible de trouver un dossier appelé `ae` qui contiendra un dossier par version de l'application AppEngine et à l'intérieur de ces dossiers, il sera possible de trouver le fichier `manifest.json`. Ce fichier contient un json avec tous les fichiers qui doivent être utilisés pour créer la version spécifique. De plus, il est possible de trouver les **vrais noms des fichiers, l'URL vers eux à l'intérieur du bucket GCP (les fichiers à l'intérieur du bucket ont changé leur nom pour leur hash sha1) et le hash sha1 de chaque fichier.**

_Remarque : il n'est pas possible de pré-prendre ce bucket car les utilisateurs GCP ne sont pas autorisés à générer des buckets utilisant le nom de domaine appspot.com._

Cependant, avec un accès en lecture et en écriture sur ce bucket, il est possible d'escalader les privilèges vers le SA attaché à la version App Engine en surveillant le bucket et chaque fois qu'un changement est effectué (nouvelle version), modifier la nouvelle version aussi rapidement que possible. De cette manière, le conteneur qui est créé à partir de ce code exécutera le code compromis.

L'attaque mentionnée peut être réalisée de plusieurs manières différentes, toutes commencent par surveiller le bucket `staging.<project-id>.appspot.com` :

- Téléchargez le code complet de la nouvelle version d'AppEngine vers un autre bucket disponible et préparez un **fichier `manifest.json` avec le nouveau nom de bucket et les hashes sha1 de ceux-ci**. Ensuite, lorsqu'une nouvelle version est créée à l'intérieur du bucket, vous devez simplement modifier le fichier `manifest.json` et télécharger le fichier malveillant.
- Téléchargez une version modifiée de `requirements.txt` qui utilisera le **code des dépendances malveillantes et mettez à jour le fichier `manifest.json`** avec le nouveau nom de fichier, l'URL et le hash de celui-ci.
- Téléchargez un **fichier `main.py` ou `app.yaml` modifié qui exécutera le code malveillant** et mettez à jour le fichier `manifest.json` avec le nouveau nom de fichier, l'URL et le hash de celui-ci.

**Vous pouvez trouver un PoC de cette attaque dans le dépôt :** [**https://github.com/carlospolop/Monitor-Backdoor-AppEngine**](https://github.com/carlospolop/Monitor-Backdoor-AppEngine)

### GCR

- **Google Container Registry** stocke les images à l'intérieur des buckets, si vous pouvez **écrire dans ces buckets**, vous pourriez être en mesure de **vous déplacer latéralement vers l'endroit où ces buckets sont exécutés.**
- Le bucket utilisé par GCR aura une URL similaire à `gs://<eu/usa/asia/nothing>.artifacts.<project>.appspot.com` (Les sous-domaines de niveau supérieur sont spécifiés [ici](https://cloud.google.com/container-registry/docs/pushing-and-pulling)).

> [!TIP]
> Ce service est obsolète, donc cette attaque n'est plus utile. De plus, Artifact Registry, le service qui remplace celui-ci, ne stocke pas les images dans des buckets.

## **Références**

- [https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/#:\~:text=apiKeys.-,create,privileges%20than%20our%20own%20user.](https://rhinosecuritylabs.com/cloud-security/privilege-escalation-google-cloud-platform-part-2/)

{{#include ../../../banners/hacktricks-training.md}}
