GCP - AppEngine Privesc
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
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
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:
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:
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
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.
appengine.applications.update
, appengine.operations.get
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.
appengine.versions.getFileContents
, appengine.versions.update
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:
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.
Last updated