# GCP - AppEngine Privesc

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

## App Engine

Pour plus d'informations sur App Engine, consultez :

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

### `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](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`**.
```bash
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.

> [!NOTE]
> 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 :
```bash
# 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 :
```bash
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**.
```bash
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.
```bash
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 changez 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 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 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 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 vérifiez les informations pertinentes de cette page** :

{{#ref}}
gcp-storage-privesc.md
{{#endref}}

### Accès en écriture sur le registre d'artefacts

Bien qu'App Engine crée des images docker à l'intérieur du registre d'artefacts. 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é.

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