GCP - AppEngine Privesc

Support 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. Tal vez los permisos get y list podrían ser evitados.

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

Por defecto, el nombre del servicio de la 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

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 llama a desplegar otra vez y espera algunos minutos.

Es posible indicar la Cuenta de Servicio a utilizar pero por defecto, se utiliza la SA predeterminada de App Engine.

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

Actualizar permisos equivalentes

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

# 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 ya has comprometido un AppEngine y tienes el permiso appengine.applications.update y actAs sobre la cuenta de servicio que puedes usar, podrías modificar la cuenta de servicio utilizada por AppEngine con:

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 a través de ssh en las instancias de App Engine de tipo flexible (no estándar). Algunos de los permisos list y get podrían no ser realmente necesarios.

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

appengine.applications.update, appengine.operations.get

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

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

appengine.versions.getFileContents, appengine.versions.update

No estoy seguro de cómo usar estos permisos o si son útiles (ten en cuenta 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 rol de IAM de uno, pero supongo que deberías poder hacerlo, tal vez cambiando el código dentro del bucket??).

Acceso de escritura sobre los buckets

Como se mencionó, las versiones de appengine generan algunos datos dentro de un bucket con el formato nombre: staging.<project-id>.appspot.com. Ten en cuenta que no es posible tomar el control de este bucket porque los usuarios de GCP no están autorizados para generar buckets usando el nombre de 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 monitoreando el bucket y cada vez que se realiza un cambio, modificar el código lo más rápido posible. De esta manera, el contenedor que se crea a partir de este código ejecutará el código con puerta trasera.

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

GCP - Storage Privesc

Acceso de escritura sobre el Registro de Artefactos

A pesar de que App Engine crea imágenes de docker dentro del Registro de Artefactos. Se probó que incluso si modificas la imagen dentro de este servicio y eliminas la instancia de App Engine (para que se despliegue una nueva) el código ejecutado no cambia. Podría ser posible que realizando un ataque de condición de carrera como con los buckets podría ser posible sobrescribir el código ejecutado, pero esto no fue probado.

Support HackTricks

Last updated