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
- Consulta los subscription plans!
- Únete al 💬 Discord group o al telegram group o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud github repos.
App Engine
Para más información sobre App Engine consulta:
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 evitarse.
You can find python code examples in https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine
By default, the name of the App service is going to be default, and there can be only 1 instance with the same name.
Para cambiarlo y crear una segunda App, en app.yaml, cambia el valor de la clave raíz por algo como service: my-second-app
cd python-docs-samples/appengine/flexible/hello_world
gcloud app deploy #Upload and start application inside the folder
Espera al menos 10–15 minutos; si no funciona, intenta desplegarlo de nuevo varias veces y espera unos minutos.
Note
Es posible indicar la Service Account a usar pero por defecto se usa la App Engine default SA.
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
Puede 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 a usar, podrías modificar la cuenta de servicio que usa 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 vía ssh en instancias de App Engine de tipo flexible (no standard). Algunos de los permisos de 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 (SA) en segundo plano que Google usará para configurar las aplicaciones, por lo 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 IAM role de una, pero supongo que deberías poder hacerlo, quizá cambiando el código dentro del bucket??).
bigquery.tables.delete, bigquery.datasets.delete & bigquery.models.delete (bigquery.models.getMetadata)
Para eliminar tablas, datasets o modelos:
# Table removal
bq rm -f -t <PROJECT_ID>.<DATASET>.<TABLE_NAME>
# Dataset removal
bq rm -r -f <PROJECT_ID>:<DATASET>
# Model removal
bq rm -m <PROJECT_ID>:<DATASET_NAME>.<MODEL_NAME>
Abuse of Scheduled Queries
Con los permisos bigquery.datasets.get, bigquery.jobs.create y iam.serviceAccounts.actAs, una identidad puede consultar metadata del dataset, iniciar BigQuery jobs y ejecutarlos usando un Service Account con privilegios superiores.
Este ataque permite el uso malicioso de Scheduled Queries para automatizar consultas (que se ejecutan con el Service Account seleccionado), lo que puede, por ejemplo, provocar que datos sensibles sean leídos y escritos en otra tabla o dataset al que el atacante sí tiene acceso — facilitando una exfiltration indirecta y continua sin necesidad de extraer los datos externamente.
Una vez que el atacante sabe qué Service Account tiene los permisos necesarios para ejecutar la consulta deseada, puede crear una configuración de Scheduled Query que se ejecute con ese Service Account y escriba periódicamente los resultados en un dataset elegido por él.
bq mk \
--transfer_config \
--project_id=<PROJECT_ID> \
--location=US \
--data_source=scheduled_query \
--target_dataset=<DEST_DATASET> \
--display_name="Generic Scheduled Query" \
--service_account_name="<SERVICE_ACCOUNT>@<PROJECT_ID>.iam.gserviceaccount.com" \
--schedule="every 10 minutes" \
--params='{
"query": "SELECT * FROM `<PROJECT_ID>.<SOURCE_DATASET>.<source_table>`;",
"destination_table_name_template": "<destination_table>",
"write_disposition": "WRITE_TRUNCATE"
}'
Acceso de escritura sobre los buckets
Como se mencionó, las versiones de AppEngine generan algunos datos dentro de un bucket con el nombre: staging.<project-id>.appspot.com. Ten en cuenta que no es posible pre-takeover este 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 a la SA adjunta 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 este modo, el contenedor que se crea a partir de ese código execute the backdoored code.
Para más información y una PoC consulta la información relevante en esta página:
Acceso de escritura sobre el 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 (por lo que se despliega una nueva), el código ejecutado no cambia.
Podría ser posible que al realizar un Race Condition attack, como con los buckets, se pudiera sobrescribir el código ejecutado, pero esto no se probó.
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
- Consulta los subscription plans!
- Únete al 💬 Discord group o al telegram group o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud github repos.
HackTricks Cloud

