[New Rule] GCP IAM Service Account Impersonation Role Granted#6215
[New Rule] GCP IAM Service Account Impersonation Role Granted#6215Aryu-RU wants to merge 4 commits into
Conversation
|
💚 CLA has been signed |
|
Signed the CLA |
|
Thanks @Samirbous — applied both suggestions:
Example event — a service-account-level Raw Cloud Audit Log: {
"protoPayload": {
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo": {
"principalEmail": "intruder@example.com",
"principalSubject": "user:intruder@example.com"
},
"requestMetadata": {
"callerIp": "203.0.113.74",
"callerSuppliedUserAgent": "google-cloud-sdk gcloud/470.0.0"
},
"serviceName": "iam.googleapis.com",
"methodName": "google.iam.admin.v1.SetIAMPolicy",
"authorizationInfo": [
{ "resource": "projects/-/serviceAccounts/103515", "permission": "iam.serviceAccounts.setIamPolicy", "granted": true }
],
"resourceName": "projects/-/serviceAccounts/deploy-prod@my-project.iam.gserviceaccount.com",
"request": {
"@type": "type.googleapis.com/google.iam.v1.SetIamPolicyRequest",
"resource": "projects/-/serviceAccounts/deploy-prod@my-project.iam.gserviceaccount.com",
"policy": {
"bindings": [
{ "role": "roles/iam.serviceAccountTokenCreator", "members": ["user:intruder@example.com"] }
]
}
},
"response": {
"@type": "type.googleapis.com/google.iam.v1.Policy",
"bindings": [
{ "role": "roles/iam.serviceAccountTokenCreator", "members": ["user:intruder@example.com"] }
]
}
},
"resource": { "type": "service_account", "labels": { "project_id": "my-project", "email_id": "deploy-prod@my-project.iam.gserviceaccount.com" } },
"timestamp": "2026-06-01T10:15:30.123456Z",
"severity": "NOTICE",
"logName": "projects/my-project/logs/cloudaudit.googleapis.com%2Factivity"
}After the GCP integration normalizes it, the rule matches on |
New Terms rule that flags when an impersonation role (serviceAccountTokenCreator, serviceAccountUser, or serviceAccountOpenIdTokenCreator) is granted on a service account via SetIamPolicy. Such grants let a principal mint tokens for or act as the target service account, enabling privilege escalation and key-less persistence. Registers the flattened request/response policy binding role sub-fields in the non-ECS schema so the query validates.
Unquote the SetIAMPolicy event.action so the version wildcard matches, and key the new terms field on user.id (the authenticated principal). The GCP audit pipeline renames principalEmail/principalSubject to user.email/user.id and empties gcp.audit.authentication_info, so the previous principal_email field would not be populated. Updates the investigation guide accordingly.
47a7864 to
0cead63
Compare
Samirbous
left a comment
There was a problem hiding this comment.
thank you for the adjustments, left few suggestion, otherwise LGTM.
Use the logs-gcp.audit-* data stream index (and matching non-ECS schema key), reduce the new terms history window to now-10d, add contributor to the author list, and update the description wording.
|
Thanks for the review and approval @Samirbous! Applied all the suggestions:
|
| account, or to act as it when deploying resources. Adversaries who have obtained sufficient privileges may grant | ||
| themselves or an attacker-controlled principal one of these roles to impersonate a higher-privileged service account, | ||
| escalating privileges and establishing durable, key-less persistence that survives credential rotation. This is a New | ||
| Terms rule that alerts when the granting principal has not been observed performing this action in the last weeks. |
There was a problem hiding this comment.
| Terms rule that alerts when the granting principal has not been observed performing this action in the last weeks. | |
| Identifies when a service account impersonation role is granted on a Google Cloud Platform (GCP) service account via a | |
| SetIamPolicy operation. Roles such as "roles/iam.serviceAccountTokenCreator", "roles/iam.serviceAccountUser", and | |
| "roles/iam.serviceAccountOpenIdTokenCreator" allow a principal to mint access or identity tokens for the target service | |
| account, or to act as it when deploying resources. Adversaries who have obtained sufficient privileges may grant | |
| themselves or an attacker-controlled principal one of these roles to impersonate a higher-privileged service account, | |
| escalating privileges and establishing durable, key-less persistence that survives credential rotation. This is a New |
No markdown rendering in rule description field.
|
|
||
| ## Setup | ||
|
|
||
| The GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.""" |
There was a problem hiding this comment.
| ## Setup | |
| The GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.""" | |
| """ |
A build time field related_integrations will be added to this rule artifact at build time. We can remove this setup note. If you'd like to keep it, just move to dedicated setup field.
See python -m detection_rules view-rule RULEPATH for related_integrations field if curious.
| tags = [ | ||
| "Domain: Cloud", | ||
| "Data Source: GCP", | ||
| "Data Source: Google Cloud Platform", |
There was a problem hiding this comment.
| "Data Source: Google Cloud Platform", | |
| "Data Source: Google Cloud Platform", | |
| "Data Source: GCP Audit Logs", |
terrancedejesus
left a comment
There was a problem hiding this comment.
Nice addition, thanks @Aryu-RU !
Add the GCP Audit Logs data source tag, replace markdown backticks with quotes in the description (which does not render markdown), and drop the setup note since related_integrations is added at build time.
|
Thanks @terrancedejesus — all three applied in c020944:
|
Issue link(s): None yet. Per CONTRIBUTING, new rules ideally start from a
New ruleissue — happy to open one if preferred; a clear summary is provided below.Summary - What I changed
Adds a new
new_termsdetection rule, GCP IAM Service Account Impersonation Role Granted, underrules/integrations/gcp/.The rule fires when a
SetIamPolicyoperation on a GCP service account (google.iam.admin.v1.SetIAMPolicy) grants an impersonation role —roles/iam.serviceAccountTokenCreator,roles/iam.serviceAccountUser, orroles/iam.serviceAccountOpenIdTokenCreator. These grants let a principal mint access/identity tokens for, oractAs, the target service account, enabling privilege escalation to a higher-privileged identity and key-less persistence that survives credential rotation.Because the GCP integration maps
protoPayload.request/responseto the flattened fieldsgcp.audit.request/gcp.audit.response(and does not surfaceserviceData.policyDelta), the granted role is read fromgcp.audit.response.bindings.role(andgcp.audit.request.policy.bindings.rolewhen present). The two queried sub-fields are registered indetection_rules/etc/non-ecs-schema.jsonunderlogs-gcp*, mirroring how the Kubernetes rules registerkubernetes.audit.requestObject.*sub-fields.Why it's novel (dedup): No existing GCP rule references
SetIamPolicy, impersonation roles, or token-creator grants. The closest rule,persistence_gcp_key_created_for_service_account.toml, only catchesCreateServiceAccountKey— a policy-binding backdoor never creates a key, so that rule does not fire. Verified across all files inrules/integrations/gcp/.Scoping / FP notes: Tightly scoped to the specific method plus three named impersonation roles, and uses
new_termson(principal_email, resource_name)over a 14-day window to suppress steady-state IaC/CI-CD noise. Known false positives (Terraform/CI-CD/onboarding grants) are documented infalse_positivesand the investigation guide, with exception guidance.MITRE: T1098 / T1098.003 (Additional Cloud Roles) under Persistence (TA0003) and Privilege Escalation (TA0004).
How To Test
python -m detection_rules validate-rule rules/integrations/gcp/persistence_gcp_service_account_impersonation_role_grant.tomlpasses.python -m detection_rules test/pytest tests/— full suite green locally (219 passed, 19 skipped).roles/iam.serviceAccountTokenCreatorto a test principal on a service account and confirm the resultinggcp.auditSetIAMPolicyevent matches the rule.Checklist
Rule: NewContributor checklist
References