Detection rules › Panther

GCP Workforce Pool Created or Updated

Severity
high
Log types
GCP.AuditLog
Tags
Account Manipulation, Additional Cloud Roles, GCP, Privilege Escalation
Reference
https://medium.com/google-cloud/detection-of-inbound-sso-persistence-techniques-in-gcp-c56f7b2a588b
Source
github.com/panther-labs/panther-analysis

MITRE ATT&CK coverage

Rule body yaml

AnalysisType: rule
Filename: gcp_workforce_pool_created_or_updated.py
RuleID: "GCP.Workforce.Pool.Created.or.Updated"
DisplayName: "GCP Workforce Pool Created or Updated"
Enabled: true
LogTypes:
  - GCP.AuditLog
Tags:
  - Account Manipulation
  - Additional Cloud Roles
  - GCP
  - Privilege Escalation
Reports:
  MITRE ATT&CK:
    - TA0003:T1136.003
    - TA0003:T1098.003
    - TA0004:T1098.003
Severity: High
DedupPeriodMinutes: 60
Threshold: 1
Runbook: >
  Ensure that the Workforce Pool creation or modification was expected. Adversaries may use this to persist or allow additional access or escalate their privilege.
Reference: https://medium.com/google-cloud/detection-of-inbound-sso-persistence-techniques-in-gcp-c56f7b2a588b
Tests:
  - Name: DeleteWorkforcePool-False
    ExpectedResult: false
    Log:
      insertId: 1plwiv7e2lay7
      logName: organizations/123456789012/logs/cloudaudit.googleapis.com%2Factivity
      operation:
        first: true
        id: locations/global/workforcePools/test-pool/operations/bigar3hp32vamefaukfkaaq000000000
        producer: iam.googleapis.com
      protoPayload:
        "@type": type.googleapis.com/google.cloud.audit.AuditLog
        authenticationInfo:
          principalEmail: user@example.com
        authorizationInfo:
          - granted: true
            permission: iam.workforcePools.delete
            resource: locations/global/workforcePools/test-pool
            resourceAttributes: {}
        methodName: google.iam.admin.v1.WorkforcePools.DeleteWorkforcePool
        request:
          "@type": type.googleapis.com/google.iam.admin.v1.DeleteWorkforcePoolRequest
          name: locations/global/workforcePools/test-pool
        requestMetadata:
          callerIp: 07da:0994:97fb:8db1:c68f:c109:fcdd:d594
          callerSuppliedUserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/119.0,gzip(gfe),gzip(gfe)
          destinationAttributes: {}
          requestAttributes:
            auth: {}
            reason: 8uSywAYQGg5Db2xpc2V1bSBGbG93cw
            time: "2023-11-17T18:58:52.165673889Z"
        resourceName: locations/global/workforcePools/test-pool
        serviceName: iam.googleapis.com
      receiveTimestamp: "2023-11-17T18:58:52.901258022Z"
      resource:
        labels:
          method: google.iam.admin.v1.WorkforcePools.DeleteWorkforcePool
          service: iam.googleapis.com
        type: audited_resource
      severity: NOTICE
      timestamp: "2023-11-17T18:58:52.158942930Z"
  - Name: UpdateWorkforcePool-True
    ExpectedResult: true
    Log:
      insertId: 1h09dxwe33hgu
      logName: organizations/123456789012/logs/cloudaudit.googleapis.com%2Factivity
      operation:
        first: true
        id: locations/global/workforcePools/test-pool/operations/bigarg7n32vamefy6ximiaq000000000
        producer: iam.googleapis.com
      protoPayload:
        "@type": type.googleapis.com/google.cloud.audit.AuditLog
        authenticationInfo:
          principalEmail: user@example.com
        authorizationInfo:
          - granted: true
            permission: iam.workforcePools.update
            resource: locations/global/workforcePools/test-pool
            resourceAttributes: {}
        methodName: google.iam.admin.v1.WorkforcePools.UpdateWorkforcePool
        request:
          "@type": type.googleapis.com/google.iam.admin.v1.UpdateWorkforcePoolRequest
          updateMask: description,sessionDuration,disabled,displayName
          workforcePool:
            description: Test pool to facilitate detection writing
            displayName: Test Pool
            name: locations/global/workforcePools/test-pool
            sessionDuration: 43200s
        requestMetadata:
          callerIp: 07da:0994:97fb:8db1:c68f:c109:fcdd:d594
          callerSuppliedUserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/119.0,gzip(gfe),gzip(gfe)
          destinationAttributes: {}
          requestAttributes:
            auth: {}
            reason: 8uSywAYQGg5Db2xpc2V1bSBGbG93cw
            time: "2023-11-17T18:53:15.208909504Z"
        resourceName: locations/global/workforcePools/test-pool
        serviceName: iam.googleapis.com
      receiveTimestamp: "2023-11-17T18:53:16.523653141Z"
      resource:
        labels:
          method: google.iam.admin.v1.WorkforcePools.UpdateWorkforcePool
          service: iam.googleapis.com
        type: audited_resource
      severity: NOTICE
      timestamp: "2023-11-17T18:53:15.200613481Z"
  - Name: CreateWorkforcePool-True
    ExpectedResult: true
    Log:
      insertId: 6432zre32u1v
      logName: organizations/123456789012/logs/cloudaudit.googleapis.com%2Factivity
      operation:
        first: true
        id: locations/global/workforcePools/test-pool/operations/bifqrwxk32vamegiyoqaoeab00000000
        producer: iam.googleapis.com
      protoPayload:
        "@type": type.googleapis.com/google.cloud.audit.AuditLog
        authenticationInfo:
          principalEmail: user@example.com
        authorizationInfo:
          - granted: true
            permission: iam.workforcePools.create
            resource: organizations/123456789012
            resourceAttributes: {}
        methodName: google.iam.admin.v1.WorkforcePools.CreateWorkforcePool
        request:
          "@type": type.googleapis.com/google.iam.admin.v1.CreateWorkforcePoolRequest
          location: locations/global
          workforcePool:
            description: Test pool
            displayName: Test Pool
            name: locations/global/workforcePools/test-pool
            parent: organizations/325169835352
            sessionDuration: 3600s
            state: ACTIVE
          workforcePoolId: test-pool
        requestMetadata:
          callerIp: 07da:0994:97fb:8db1:c68f:c109:fcdd:d594
          callerSuppliedUserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/119.0,gzip(gfe),gzip(gfe)
          destinationAttributes: {}
          requestAttributes:
            auth: {}
            reason: 8uSywAYQGg5Db2xpc2V1bSBGbG93cw
            time: "2023-11-17T18:47:53.284817626Z"
        resourceName: organizations/325169835352
        serviceName: iam.googleapis.com
      receiveTimestamp: "2023-11-17T18:47:54.138395349Z"
      resource:
        labels:
          method: google.iam.admin.v1.WorkforcePools.CreateWorkforcePool
          service: iam.googleapis.com
        type: audited_resource
      severity: NOTICE
      timestamp: "2023-11-17T18:47:53.276929945Z"

Detection logic

Condition

protoPayload.methodName in ["google.iam.admin.v1.WorkforcePools.CreateWorkforcePool", "google.iam.admin.v1.WorkforcePools.UpdateWorkforcePool"]

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
protoPayload.methodNamein
  • google.iam.admin.v1.WorkforcePools.CreateWorkforcePool
  • google.iam.admin.v1.WorkforcePools.UpdateWorkforcePool

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
principalEmailprotoPayload.authenticationInfo.principalEmail