AnalysisType: rule
LogTypes:
- GCP.AuditLog
Description: >
Detects compute.instances.create method for privilege escalation in GCP. This rule identifies when users
create compute instances with service accounts that may lead to privilege escalation. Known good service accounts
(GKE, Kubernetes, compute automation) are excluded to reduce false positives.
DisplayName: "GCP compute.instances.create Privilege Escalation"
RuleID: "GCP.compute.instances.create.Privilege.Escalation"
Enabled: true
Reference: https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/
Runbook: |
1. Validate whether this compute instance creation with service account was authorized.
2. Check if the service account attached has excessive privileges.
3. Verify if the user creating the instance has a legitimate need for the service account permissions.
4. If unauthorized, revoke the instance access and investigate for compromise.
Reports:
MITRE ATT&CK:
- TA0004:T1548 # Abuse Elevation Control Mechanism
Severity: High
Filename: gcp_computeinstances_create_privilege_escalation.py
DedupPeriodMinutes: 1440
Threshold: 1
Tests:
- Name: GCP compute.instances - Potential Privilege Escalation
ExpectedResult: true
Log:
{
"protoPayload":
{
"at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo":
{
"principalEmail": "some.user@company.com",
"principalSubject": "user:some.user@company.com",
},
"authorizationInfo":
[
{
"granted": true,
"permission": "compute.instances.create",
"resource": "projects/some-project/zones/us-central1-f/instances/abc",
"resourceAttributes":
{
"name": "projects/some-project/zones/us-central1-f/instances/abc",
"service": "compute",
"type": "compute.instances",
},
},
{
"granted": true,
"permission": "compute.disks.create",
"resource": "projects/some-project/zones/us-central1-f/disks/abc",
"resourceAttributes":
{
"name": "projects/some-project/zones/us-central1-f/disks/abc",
"service": "compute",
"type": "compute.disks",
},
},
{
"granted": true,
"permission": "compute.subnetworks.use",
"resource": "projects/some-project/regions/us-central1/subnetworks/default",
"resourceAttributes":
{
"name": "projects/some-project/regions/us-central1/subnetworks/default",
"service": "compute",
"type": "compute.subnetworks",
},
},
{
"granted": true,
"permission": "compute.subnetworks.useExternalIp",
"resource": "projects/some-project/regions/us-central1/subnetworks/default",
"resourceAttributes":
{
"name": "projects/some-project/regions/us-central1/subnetworks/default",
"service": "compute",
"type": "compute.subnetworks",
},
},
{
"granted": true,
"permission": "compute.instances.setMetadata",
"resource": "projects/some-project/zones/us-central1-f/instances/abc",
"resourceAttributes":
{
"name": "projects/some-project/zones/us-central1-f/instances/abc",
"service": "compute",
"type": "compute.instances",
},
},
{
"granted": true,
"permission": "compute.instances.setServiceAccount",
"resource": "projects/some-project/zones/us-central1-f/instances/abc",
"resourceAttributes":
{
"name": "projects/some-project/zones/us-central1-f/instances/abc",
"service": "compute",
"type": "compute.instances",
},
},
],
"methodName": "v1.compute.instances.insert",
"request":
{
"@type": "type.googleapis.com/compute.instances.insert",
"disks": ...,
"machineType": ...,
"name": ...,
"networkInterfaces": ...,
"serviceAccounts":
[
{
"email": "abcmail@some-project.iam.gserviceaccount.com",
"scopes":
[
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/iam",
],
},
],
},
"requestMetadata":
{
"callerIP": "1.2.3.4",
"callerSuppliedUserAgent": "(gzip),gzip(gfe)",
"destinationAttributes": {},
"requestAttributes":
{ "auth": {}, "time": "2024-01-30T12:52:36.003867Z" },
},
"resourceLocation": ...,
"resourceName": "projects/some-project/zones/us-central1-f/instances/abc",
"response":
{
"@type": "type.googleapis.com/operation",
"id": "8758546889396539388",
"insertTime": "2024-01-30T04:52:35.886-08:00",
"name": "operation-1706619154623-610293c7a6a25-934f1c35-1efebb12",
"operationType": "insert",
"progress": "0",
"selfLink": "https://www.googleapis.com/compute/v1/projects/some-project/zones/us-central1-f/operations/operation-1706619154623-610293c7a6a25-934f1c35-1efebb12",
"selfLinkWithId": "https://www.googleapis.com/compute/v1/projects/some-project/zones/us-central1-f/operations/8758546889396539388",
"startTime": "2024-01-30T04:52:35.887-08:00",
"status": "RUNNING",
"targetId": "1454427709413609468",
"targetLink": "https://www.googleapis.com/compute/v1/projects/some-project/zones/us-central1-f/instances/abc",
"user": "some.user@company.com",
"zone": "https://www.googleapis.com/compute/v1/projects/some-project/zones/us-central1-f",
},
"serviceName": "compute.googleapis.com",
},
"receiveTimestamp": "2024-01-30 12:52:36.642422049",
"resource":
{
"labels":
{
"instance_id": "1454427709413609468",
"project_id": "some-project",
"zone": "us-central1-f",
},
"type": "gce_instance",
},
"severity": "NOTICE",
"timestamp": "2024-01-30 12:52:34.676384000",
}
- Name: GCP compute.instances - Error
ExpectedResult: false
Log:
{
"protoPayload":
{
"at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo":
{
"principalEmail": "some.user@company.com",
"principalSubject": "user:some.user@company.com",
},
"authorizationInfo":
[
{
"granted": true,
"permission": "compute.instances.create",
"resource": "projects/some-project/zones/us-central1-f/instances/abc",
"resourceAttributes":
{
"name": "projects/some-project/zones/us-central1-f/instances/abc",
"service": "compute",
"type": "compute.instances",
},
},
{
"granted": true,
"permission": "compute.disks.create",
"resource": "projects/some-project/zones/us-central1-f/disks/abc",
"resourceAttributes":
{
"name": "projects/some-project/zones/us-central1-f/disks/abc",
"service": "compute",
"type": "compute.disks",
},
},
{
"granted": true,
"permission": "compute.subnetworks.use",
"resource": "projects/some-project/regions/us-central1/subnetworks/default",
"resourceAttributes":
{
"name": "projects/some-project/regions/us-central1/subnetworks/default",
"service": "compute",
"type": "compute.subnetworks",
},
},
{
"granted": true,
"permission": "compute.subnetworks.useExternalIp",
"resource": "projects/some-project/regions/us-central1/subnetworks/default",
"resourceAttributes":
{
"name": "projects/some-project/regions/us-central1/subnetworks/default",
"service": "compute",
"type": "compute.subnetworks",
},
},
{
"granted": true,
"permission": "compute.instances.setMetadata",
"resource": "projects/some-project/zones/us-central1-f/instances/abc",
"resourceAttributes":
{
"name": "projects/some-project/zones/us-central1-f/instances/abc",
"service": "compute",
"type": "compute.instances",
},
},
{
"granted": true,
"permission": "compute.instances.setServiceAccount",
"resource": "projects/some-project/zones/us-central1-f/instances/abc",
"resourceAttributes":
{
"name": "projects/some-project/zones/us-central1-f/instances/abc",
"service": "compute",
"type": "compute.instances",
},
},
],
"methodName": "v1.compute.instances.insert",
"request":
{
"@type": ...,
"disks": ...,
"machineType": ...,
"name": ...,
"networkInterfaces": ...,
"serviceAccounts":
[
{
"email": "abcmail@some-project.iam.gserviceaccount.com",
"scopes":
[
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/iam",
],
},
],
},
"requestMetadata": ...,
"resourceLocation": ...,
"resourceName": "projects/some-project/zones/us-central1-f/instances/abc",
"response":
{
"@type": "type.googleapis.com/error",
"error":
{
"code": 404,
"errors":
[
{
"domain": "global",
"message": "The resource 'abc' was not found",
"reason": "notFound",
},
],
"message": "The resource 'abc' was not found",
},
},
"serviceName": "compute.googleapis.com",
"status":
{ "code": 5, "message": "The resource 'abc' was not found" },
},
"receiveTimestamp": "2024-01-30 11:03:56.719662927",
"resource":
{
"labels":
{
"instance_id": "",
"project_id": "some-project",
"zone": "us-central1-f",
},
"type": "gce_instance",
},
"severity": "ERROR",
"timestamp": "2024-01-30 11:03:55.700872000",
}
- Name: GCP compute.instances - Not All Permissions
ExpectedResult: false
Log:
{
"protoPayload":
{
"at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo":
{
"principalEmail": "some.user@company.com",
"principalSubject": "user:some.user@company.com",
},
"authorizationInfo":
[
{
"granted": true,
"permission": "compute.instances.create",
"resource": "projects/some-project/zones/us-central1-f/instances/abc",
"resourceAttributes":
{
"name": "projects/some-project/zones/us-central1-f/instances/abc",
"service": "compute",
"type": "compute.instances",
},
},
{
"granted": true,
"permission": "compute.disks.create",
"resource": "projects/some-project/zones/us-central1-f/disks/abc",
"resourceAttributes":
{
"name": "projects/some-project/zones/us-central1-f/disks/abc",
"service": "compute",
"type": "compute.disks",
},
},
{
"granted": true,
"permission": "compute.subnetworks.use",
"resource": "projects/some-project/regions/us-central1/subnetworks/default",
"resourceAttributes":
{
"name": "projects/some-project/regions/us-central1/subnetworks/default",
"service": "compute",
"type": "compute.subnetworks",
},
},
{
"granted": true,
"permission": "compute.subnetworks.useExternalIp",
"resource": "projects/some-project/regions/us-central1/subnetworks/default",
"resourceAttributes":
{
"name": "projects/some-project/regions/us-central1/subnetworks/default",
"service": "compute",
"type": "compute.subnetworks",
},
},
{
"granted": true,
"permission": "compute.instances.setMetadata",
"resource": "projects/some-project/zones/us-central1-f/instances/abc",
"resourceAttributes":
{
"name": "projects/some-project/zones/us-central1-f/instances/abc",
"service": "compute",
"type": "compute.instances",
},
},
],
"methodName": "v1.compute.instances.insert",
"request": ...,
"requestMetadata": ...,
"resourceLocation": ...,
"resourceName": ...,
"response": ...,
"serviceName": ...,
},
"receiveTimestamp": ...,
"resource": ...,
}
# ------ paired body: gcp_computeinstances_create_privilege_escalation.py ------
from panther_gcp_helpers import gcp_alert_context
REQUIRED_PERMISSIONS = [
"compute.disks.create",
"compute.instances.create",
"compute.instances.setMetadata",
"compute.instances.setServiceAccount",
"compute.subnetworks.use",
"compute.subnetworks.useExternalIp",
]
def rule(event):
if event.deep_get("protoPayload", "response", "error"):
return False
method = event.deep_get("protoPayload", "methodName", default="METHOD_NOT_FOUND")
if not method.endswith("compute.instances.insert"):
return False
# Skip allowlisted actors
principal = event.deep_get("protoPayload", "authenticationInfo", "principalEmail", default="")
if principal.endswith("@cloudservices.gserviceaccount.com"):
return False
granted_permissions = {}
for auth in event.deep_walk("protoPayload", "authorizationInfo") or []:
granted_permissions[auth.get("permission")] = auth.get("granted")
for permission in REQUIRED_PERMISSIONS:
if not granted_permissions.get(permission):
return False
return True
def title(event):
actor = event.deep_get(
"protoPayload", "authenticationInfo", "principalEmail", default="<ACTOR_NOT_FOUND>"
)
service_accounts = event.deep_get("protoPayload", "request", "serviceAccounts")
if not service_accounts:
service_account_emails = "<SERVICE_ACCOUNT_EMAILS_NOT_FOUND>"
else:
service_account_emails = [service_acc["email"] for service_acc in service_accounts]
project = event.deep_get("resource", "labels", "project_id", default="<PROJECT_NOT_FOUND>")
return (
f"[GCP]: [{actor}] created a new Compute Engine instance with [{service_account_emails}] "
f"Service Account on project [{project}]"
)
def alert_context(event):
context = gcp_alert_context(event)
service_accounts = event.deep_get("protoPayload", "request", "serviceAccounts")
if not service_accounts:
service_account_emails = "<SERVICE_ACCOUNT_EMAILS_NOT_FOUND>"
else:
service_account_emails = [service_acc["email"] for service_acc in service_accounts]
context["serviceAccount"] = service_account_emails
return context