GCP - AppEngine Privesc

Support HackTricks

App Engine

Pour plus d'informations sur App Engine, consultez :

GCP - App Engine Enum

appengine.applications.get, appengine.instances.get, appengine.instances.list, appengine.operations.get, appengine.operations.list, appengine.services.get, appengine.services.list, appengine.versions.create, appengine.versions.get, appengine.versions.list, cloudbuild.builds.get,iam.serviceAccounts.actAs, resourcemanager.projects.get, storage.objects.create, storage.objects.list

Ce sont les permissions nécessaires pour déployer une application en utilisant gcloud cli. Peut-être que les permissions get et list pourraient être évitées.

Vous pouvez trouver des exemples de code python sur https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine

Par défaut, le nom du service App sera default, et il ne peut y avoir qu'une seule instance avec le même nom. Pour le changer et créer une deuxième application, dans app.yaml, changez la valeur de la clé racine en quelque chose comme service: my-second-app

cd python-docs-samples/appengine/flexible/hello_world
gcloud app deploy #Upload and start application inside the folder

Donnez-lui au moins 10 à 15 minutes, si cela ne fonctionne pas, appelez déployer une autre fois et attendez quelques minutes.

Il est possible d'indiquer le compte de service à utiliser mais par défaut, le compte de service par défaut de l'App Engine est utilisé.

L'URL de l'application est quelque chose comme https://<proj-name>.oa.r.appspot.com/ ou https://<service_name>-dot-<proj-name>.oa.r.appspot.com

Mettre à jour les autorisations équivalentes

Vous pourriez avoir suffisamment d'autorisations pour mettre à jour un AppEngine mais pas pour en créer un nouveau. Dans ce cas, voici comment vous pourriez mettre à jour l'App Engine actuel :

# Find the code of the App Engine in the buckets
gsutil ls

# Download code
mkdir /tmp/appengine2
cd /tmp/appengine2
## In this case it was found in this custom bucket but you could also use the
## buckets generated when the App Engine is created
gsutil cp gs://appengine-lab-1-gcp-labs-4t04m0i6-3a97003354979ef6/labs_appengine_1_premissions_privesc.zip .
unzip labs_appengine_1_premissions_privesc.zip

## Now modify the code..

## If you don't have an app.yaml, create one like:
cat >> app.yaml <<EOF
runtime: python312

entrypoint: gunicorn -b :\$PORT main:app

env_variables:
A_VARIABLE: "value"
EOF

# Deploy the changes
gcloud app deploy

# Update the SA if you need it (and if you have actas permissions)
gcloud app update --service-account=<sa>@$PROJECT_ID.iam.gserviceaccount.com

Si vous avez déjà compromis un AppEngine et que vous avez la permission appengine.applications.update et actAs sur le compte de service que vous pourriez modifier le compte de service utilisé par AppEngine avec :

gcloud app update --service-account=<sa>@$PROJECT_ID.iam.gserviceaccount.com

appengine.instances.enableDebug, appengine.instances.get, appengine.instances.list, appengine.operations.get, appengine.services.get, appengine.services.list, appengine.versions.get, appengine.versions.list, compute.projects.get

Avec ces autorisations, il est possible de se connecter via ssh dans les instances App Engine de type flexible (pas standard). Certaines des autorisations list et get pourraient ne pas être vraiment nécessaires.

gcloud app instances ssh --service <app-name> --version <version-id> <ID>

appengine.applications.update, appengine.operations.get

Je pense que cela ne change que le compte de service de fond que Google utilisera pour configurer les applications, donc je ne pense pas que vous puissiez en abuser pour voler le compte de service.

gcloud app update --service-account=<sa_email>

appengine.versions.getFileContents, appengine.versions.update

Je ne suis pas sûr de la façon d'utiliser ces autorisations ou si elles sont utiles (notez que lorsque vous modifiez le code, une nouvelle version est créée, donc je ne sais pas si vous pouvez simplement mettre à jour le code ou le rôle IAM de l'un, mais je suppose que vous devriez pouvoir le faire, peut-être en changeant le code à l'intérieur du bucket ??).

Accès en écriture sur les buckets

Comme mentionné, 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. Notez qu'il n'est pas possible de pré-prendre ce bucket car les utilisateurs GCP ne sont pas autorisés à générer des buckets en 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 au SA attaché à la version AppEngine en surveillant le bucket et chaque fois qu'un changement est effectué, modifier le code aussi rapidement que possible. De cette manière, le conteneur qui est créé à partir de ce code exécutera le code compromis.

Pour plus d'informations et un PoC, consultez les informations pertinentes de cette page :

GCP - Storage Privesc

Accès en écriture sur l'Artifact Registry

Bien qu'App Engine crée des images docker à l'intérieur de l'Artifact Registry. Il a été testé que même si vous modifiez l'image à l'intérieur de ce service et supprimez l'instance App Engine (donc une nouvelle est déployée), le code exécuté ne change pas. Il pourrait être possible qu'en effectuant une attaque de condition de course comme avec les buckets, il pourrait être possible de remplacer le code exécuté, mais cela n'a pas été testé.

Support HackTricks

Last updated