GCP - Storage Privesc

Support HackTricks

Storage

Informations de base :

storage.objects.get

Cette permission vous permet de télécharger des fichiers stockés dans Cloud Storage. Cela vous permettra potentiellement d'escalader les 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 l'un 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 :

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 les 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.

# 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.

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, 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 repo : 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 repo : 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 bucket différent et 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 repo : 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).

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

Soutenir HackTricks

Last updated