GCP - AppEngine Privesc

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 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 só pode haver 1 instância com o mesmo nome.
Para alterá-lo e criar um segundo App, em app.yaml, altere o valor da chave raiz para algo como service: my-second-app

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, tente deploy novamente e aguarde alguns minutos.

Note

É possível indicar o Service Account a ser usado mas por padrão, o App Engine default SA é usado.

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:

# 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 a ser usada, você pode modificar a conta de serviço usada pelo AppEngine com:

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.

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

appengine.applications.update, appengine.operations.get

Acho que isso apenas altera a SA em segundo plano que o google usará para configurar as aplicações, então não creio que seja possível abusar disso para roubar a service account.

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 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 IAM role de uma, mas acho que deveria ser possível, talvez mudando o código dentro do bucket??).

bigquery.tables.delete, bigquery.datasets.delete & bigquery.models.delete (bigquery.models.getMetadata)

Para remover tables, dataset ou models:

# 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>

Abuso de Scheduled Queries

Com as permissões bigquery.datasets.get, bigquery.jobs.create e iam.serviceAccounts.actAs, uma identidade pode consultar metadados de datasets, iniciar jobs do BigQuery e executá-los usando um Service Account com privilégios mais elevados.

Esse ataque permite o uso malicioso de Scheduled Queries para automatizar consultas (executadas sob o Service Account escolhido), que podem, por exemplo, levar à leitura de dados sensíveis e à escrita desses dados em outra tabela ou dataset ao qual o atacante tem acesso — facilitando exfiltração indireta e contínua sem precisar extrair os dados externamente.

Uma vez que o atacante saiba qual Service Account possui as permissões necessárias para executar a consulta desejada, ele pode criar uma configuração de Scheduled Query que rode usando esse Service Account e periodicamente grave os resultados em um dataset de sua escolha.

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"
}'

Acesso de escrita sobre os buckets

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

No entanto, com acesso de leitura e escrita sobre esse bucket, é possível escalar privilégios para a SA associada à versão do App Engine monitorando o bucket e, sempre que uma mudança for realizada, modificar o código o mais rápido possível. Dessa forma, o container que é criado a partir desse código irá execute the backdoored code.

Para mais informações e uma PoC, consulte as informações relevantes nesta página:

GCP - Storage Privesc

Acesso de escrita no Artifact Registry

Embora o App Engine crie imagens docker dentro do Artifact Registry, foi testado que mesmo se você modificar a imagem dentro desse serviço e remover a instância do App Engine (fazendo com que uma nova seja implantada), o código executado não muda.
Pode ser possível que, realizando um Race Condition attack semelhante ao dos buckets, seja 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