Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GCP SSO persistence rules #954

Merged
merged 6 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions packs/gcp_audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,25 @@ PackID: PantherManaged.GCP.Audit
Description: Group of all Google Cloud Platform (GCP) Audit detections
PackDefinition:
IDs:
- GCP.Access.Attempts.Violating.IAP.Access.Controls
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The +/- in this file are from me sorting the IDs alphabetically.

- GCP.Access.Attempts.Violating.VPC.Service.Controls
- GCP.BigQuery.Large.Scan
- GCP.Cloud.Storage.Buckets.Modified.Or.Deleted
- GCP.Destructive.Queries
- GCP.GCS.IAMChanges
- GCP.GCS.Public
- GCP.IAM.CorporateEmail
- GCP.IAM.CustomRoleChanges
- GCP.IAM.OrgFolderIAMChanges
- GCP.SQL.ConfigChanges
- GCP.Access.Attempts.Violating.VPC.Service.Controls
- GCP.Access.Attempts.Violating.IAP.Access.Controls
- GCP.VPC.Flow.Logs.Disabled
- GCP.BigQuery.Large.Scan
- GCP.Destructive.Queries
- GCP.Inbound.SSO.Profile.Created
- GCP.Logging.Settings.Modified
- GCP.Cloud.Storage.Buckets.Modified.Or.Deleted
- GCP.Permissions.Granted.to.Create.or.Manage.Service.Account.Key
- GCP.User.Added.to.IAP.Protected.Service
- GCP.Service.Account.or.Keys.Created
- GCP.SQL.ConfigChanges
- GCP.User.Added.to.IAP.Protected.Service
- GCP.VPC.Flow.Logs.Disabled
- GCP.Workforce.Pool.Created.or.Updated
- GCP.Workload.Identity.Pool.Created.or.Updated
# Data model
- Standard.GCP.AuditLog
# Globals used in these rules/policies
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
METHODS = [
"google.admin.AdminService.inboundSsoProfileCreated",
"google.admin.AdminService.inboundSsoProfileUpdated",
]


def rule(event):
return event.deep_get("protoPayload", "methodName", default="") in METHODS


def title(event):
actor = event.deep_get(
"protoPayload", "authenticationInfo", "principalEmail", default="<ACTOR_NOT_FOUND>"
)
event_name = event.deep_walk(
"protoPayload", "metadata", "event", "eventName", default="<EVENT_NAME_NOT_FOUND>"
)

resource = organization_id = event.deep_walk(
"protoPayload", "resourceName", default="<RESOURCE_NOT_FOUND>"
).split("/")

organization_id = resource[resource.index("organizations") + 1]

return f"GCP: [{actor}] performed {event_name} in organization {organization_id}"


def alert_context(event):
return {
"resourceName": event.deep_get(
"protoPayload", "resourceName", default="<RESOURCE_NOT_FOUND>"
),
"serviceName": event.deep_get("protoPayload", "serviceName", default="<SERVICE_NOT_FOUND>"),
}
136 changes: 136 additions & 0 deletions rules/gcp_audit_rules/gcp_inbound_sso_profile_created_or_updated.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
AnalysisType: rule
Filename: gcp_inbound_sso_profile_created_or_updated.py
RuleID: "GCP.Inbound.SSO.Profile.Created"
DisplayName: "GCP Inbound SSO Profile Created"
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
Tests:
- Name: InboundSsoProfileDeleted-False
ExpectedResult: false
Log:
insertId: chtsf1e7iek8
logName: organizations/325169835352/logs/cloudaudit.googleapis.com%2Factivity
protoPayload:
'@type': type.googleapis.com/google.cloud.audit.AuditLog
authenticationInfo:
principalEmail: [email protected]
metadata:
'@type': type.googleapis.com/ccc_hosted_reporting.ActivityProto
activityId:
timeUsec: "1700250882598435"
uniqQualifier: "6879748717081533837"
event:
- eventId: dd0c44e2
eventName: INBOUND_SSO_PROFILE_DELETED
eventType: INBOUND_SSO_SETTINGS
parameter:
- label: LABEL_OPTIONAL
name: INBOUND_SSO_PROFILE_NAME
type: TYPE_STRING
value: inboundSamlSsoProfiles/01lmf7wd3jt9atc
methodName: google.admin.AdminService.inboundSsoProfileDeleted
requestMetadata:
destinationAttributes: {}
requestAttributes: {}
resourceName: organizations/123456789012/inboundSsoSettings
serviceName: admin.googleapis.com
receiveTimestamp: "2023-11-17T19:54:43.367407397Z"
resource:
labels:
method: google.admin.AdminService.inboundSsoProfileDeleted
service: admin.googleapis.com
type: audited_resource
severity: NOTICE
timestamp: "2023-11-17T19:54:42.598435Z"
- Name: InboundSsoProfileUpdated-True
ExpectedResult: true
Log:
insertId: crpr6bdcjfg
logName: organizations/123456789012/logs/cloudaudit.googleapis.com%2Factivity
protoPayload:
'@type': type.googleapis.com/google.cloud.audit.AuditLog
authenticationInfo:
principalEmail: user@@example.com
metadata:
'@type': type.googleapis.com/ccc_hosted_reporting.ActivityProto
activityId:
timeUsec: "1700250956956215"
uniqQualifier: "2009471038637356014"
event:
- eventId: bdbc47ad
eventName: INBOUND_SSO_PROFILE_UPDATED
eventType: INBOUND_SSO_SETTINGS
parameter:
- label: LABEL_OPTIONAL
name: INBOUND_SSO_PROFILE_CHANGES
type: TYPE_STRING
value: 'Display Name : { oldValue: Test Profile, newValue: Test Profile Update}'
- label: LABEL_OPTIONAL
name: INBOUND_SSO_PROFILE_NAME
type: TYPE_STRING
value: inboundSamlSsoProfiles/03vsz0843d02br4
methodName: google.admin.AdminService.inboundSsoProfileUpdated
requestMetadata:
destinationAttributes: {}
requestAttributes: {}
resourceName: organizations/123456789012/inboundSsoSettings
serviceName: admin.googleapis.com
receiveTimestamp: "2023-11-17T19:55:57.417198068Z"
resource:
labels:
method: google.admin.AdminService.inboundSsoProfileUpdated
service: admin.googleapis.com
type: audited_resource
severity: NOTICE
timestamp: "2023-11-17T19:55:56.956215Z"
- Name: InboundSsoProfileCreated-True
ExpectedResult: true
Log:
insertId: -rqtp5gefopij
logName: organizations/123456789012/logs/cloudaudit.googleapis.com%2Factivity
protoPayload:
'@type': type.googleapis.com/google.cloud.audit.AuditLog
authenticationInfo:
principalEmail: [email protected]
metadata:
'@type': type.googleapis.com/ccc_hosted_reporting.ActivityProto
activityId:
timeUsec: "1700250924521362"
uniqQualifier: "6051731645161637785"
event:
- eventId: 637d2b33
eventName: INBOUND_SSO_PROFILE_CREATED
eventType: INBOUND_SSO_SETTINGS
parameter:
- label: LABEL_OPTIONAL
name: INBOUND_SSO_PROFILE_NAME
type: TYPE_STRING
value: inboundSamlSsoProfiles/03vsz0843d02br4
methodName: google.admin.AdminService.inboundSsoProfileCreated
requestMetadata:
destinationAttributes: {}
requestAttributes: {}
resourceName: organizations/123456789012/inboundSsoSettings
serviceName: admin.googleapis.com
receiveTimestamp: "2023-11-17T19:55:25.012649522Z"
resource:
labels:
method: google.admin.AdminService.inboundSsoProfileCreated
service: admin.googleapis.com
type: audited_resource
severity: NOTICE
timestamp: "2023-11-17T19:55:24.521362Z"
32 changes: 32 additions & 0 deletions rules/gcp_audit_rules/gcp_workforce_pool_created_or_updated.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
METHODS = [
"google.iam.admin.v1.WorkforcePools.CreateWorkforcePool",
"google.iam.admin.v1.WorkforcePools.UpdateWorkforcePool",
]


def rule(event):
return event.deep_get("protoPayload", "methodName", default="") in METHODS


def title(event):
actor = event.deep_get(
"protoPayload", "authenticationInfo", "principalEmail", default="<ACTOR_NOT_FOUND>"
)
workforce_pool = event.deep_get("protoPayload", "request", "workforcePool", "name").split("/")[
-1
]

resource = organization_id = event.deep_get("logName", default="<LOG_NAME_NOT_FOUND>").split(
"/"
)

organization_id = resource[resource.index("organizations") + 1]

return (
f"GCP: [{actor}] created or updated workforce pool "
f"[{workforce_pool}] in organization [{organization_id}]"
)


def alert_context(event):
return event.deep_get("protoPayload", "request", "workforcePool", default={})
154 changes: 154 additions & 0 deletions rules/gcp_audit_rules/gcp_workforce_pool_created_or_updated.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
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
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: [email protected]
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: [email protected]
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: [email protected]
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"
Loading