GCP - AppEngine Privesc

Tip

Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

App Engine

Para más información sobre App Engine consulta:

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

Esos son los permisos necesarios para desplegar una App usando gcloud cli. Quizá los get y list podrían omitirse.

Puedes encontrar ejemplos de código python en https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine

Por defecto, el nombre del servicio App será default, y solo puede haber 1 instancia con el mismo nombre.
Para cambiarlo y crear una segunda App, en app.yaml, cambia el valor de la clave raíz a algo como service: my-second-app

Desplegar una aplicación de App Engine ```bash cd python-docs-samples/appengine/flexible/hello_world gcloud app deploy #Upload and start application inside the folder ```

Dale al menos 10-15 minutos; si no funciona, vuelve a ejecutar deploy another of times y espera unos minutos.

Note

Es posible indicar el Service Account a usar pero por defecto se usa la SA predeterminada de App Engine.

La URL de la aplicación es algo así como https://<proj-name>.oa.r.appspot.com/ o https://<service_name>-dot-<proj-name>.oa.r.appspot.com

Actualizar permisos equivalentes

Puede que tengas permisos suficientes para actualizar un AppEngine pero no para crear uno nuevo. En ese caso, así es como podrías actualizar el App Engine actual:

Actualizar aplicación App Engine existente ```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=@$PROJECT_ID.iam.gserviceaccount.com

</details>

Si ya has comprometido un AppEngine y tienes el permiso **`appengine.applications.update`** y **actAs** sobre la cuenta de servicio a usar, podrías modificar la cuenta de servicio usada por AppEngine con:

<details>
<summary>Actualizar la cuenta de servicio de App Engine</summary>
```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

Con estos permisos, es posible iniciar sesión por ssh en instancias de App Engine del tipo flexible (no standard). Algunos de los permisos list y get podrían no ser realmente necesarios.

SSH a una instancia de App Engine ```bash gcloud app instances ssh --service --version ```

appengine.applications.update, appengine.operations.get

Creo que esto solo cambia la SA de fondo que google usará para configurar las aplicaciones, así que no creo que puedas abusar de esto para robar la cuenta de servicio.

Actualizar la cuenta de servicio de la aplicación ```bash gcloud app update --service-account= ```

appengine.versions.getFileContents, appengine.versions.update

No estoy seguro de cómo usar estos permisos o si son útiles (nota que cuando cambias el código se crea una nueva versión, así que no sé si puedes simplemente actualizar el código o el IAM role de una, pero supongo que deberías poder, ¿tal vez cambiando el código dentro del bucket?).

Write Access over the buckets

Como se mencionó, las versiones de AppEngine generan algunos datos dentro de un bucket con el formato: staging.<project-id>.appspot.com. Ten en cuenta que no es posible pre-takeover this bucket porque los usuarios de GCP no están autorizados a crear buckets usando el dominio appspot.com.

Sin embargo, con acceso de lectura y escritura sobre este bucket, es posible escalar privilegios al SA adjunto a la versión de AppEngine monitorizando el bucket y, cada vez que se realice un cambio, modificar el código lo más rápido posible. De esta manera, el container que se cree a partir de ese código execute the backdoored code.

Para más información y un PoC consulta la información relevante en esta página:

GCP - Storage Privesc

Acceso de escritura sobre Artifact Registry

Aunque App Engine crea imágenes docker dentro de Artifact Registry, se comprobó que incluso si modificas la imagen dentro de este servicio y se elimina la instancia de App Engine (de modo que se despliega una nueva), el code executed doesn’t change.
Podría ser posible que realizando un Race Condition attack como con los buckets sea posible sobrescribir el código ejecutado, pero esto no fue probado.

Tip

Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks