Detection rules › Panther
GCP Firewall Rule Modified
This rule detects modifications to GCP firewall rules.
Rule body yaml
AnalysisType: rule
DedupPeriodMinutes: 90
DisplayName: GCP Firewall Rule Modified
Enabled: true
Filename: gcp_firewall_rule_modified.py
RuleID: "GCP.Firewall.Rule.Modified"
Severity: Low
LogTypes:
- GCP.AuditLog
Tags:
- GCP
- Firewall
- Networking
- Infrastructure
Description: >
This rule detects modifications to GCP firewall rules.
Runbook: >
Ensure that the rule modification was expected. Firewall rule changes can cause service interruptions or outages.
Reference: https://cloud.google.com/firewall/docs/about-firewalls
Tests:
- Name: compute.firewalls.update-should-alert
LogType: GCP.AuditLog
ExpectedResult: true
Log:
{
"insertid": "-xxxxxxxxxxxx",
"logname": "projects/test-project-123456/cloudaudit.googleapis.com%2Factivity",
"operation":
{
"first": true,
"id": "operation-1684869580331-5fc6144d418a9-e1332ca3-59c615ac",
"producer": "compute.googleapis.com",
},
"protoPayload":
{
"at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo": { "principalEmail": "user@domain.com" },
"authorizationInfo":
[
{
"granted": true,
"permission": "compute.firewalls.update",
"resourceAttributes":
{
"name": "projects/test-project-123456/global/firewalls/firewall-create",
"service": "compute",
"type": "compute.firewalls",
},
},
{
"granted": true,
"permission": "compute.networks.updatePolicy",
"resourceAttributes":
{
"name": "projects/test-project-123456/global/networks/default",
"service": "compute",
"type": "compute.networks",
},
},
],
"methodName": "v1.compute.firewalls.patch",
"request":
{
"@type": "type.googleapis.com/compute.firewalls.patch",
"denieds": [{ "IPProtocol": "all" }],
},
"requestMetadata":
{
"callerIP": "12.12.12.12",
"callerSuppliedUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36,gzip(gfe),gzip(gfe)",
"destinationAttributes": {},
"requestAttributes":
{
"auth": {},
"reason": "8uSywAYQGg5Db2xpc2V1bSBGbG93cw",
"time": "2023-05-23T19:19:41.154751Z",
},
},
"resourceName": "projects/test-project-123456/global/firewalls/firewall-create",
"response":
{
"@type": "type.googleapis.com/operation",
"id": "896785227463044899",
"insertTime": "2023-05-23T12:19:40.876-07:00",
"name": "operation-1684869580331-5fc6144d418a9-e1332ca3-59c615ac",
"operationType": "patch",
"progress": "0",
"selfLink": "https://www.googleapis.com/compute/v1/projects/test-project-123456/global/operations/operation-1684869580331-5fc6144d418a9-e1332ca3-59c615ac",
"selfLinkWithId": "https://www.googleapis.com/compute/v1/projects/test-project-123456/global/operations/896785227463044899",
"startTime": "2023-05-23T12:19:40.888-07:00",
"status": "RUNNING",
"targetId": "6563507997690081088",
"targetLink": "https://www.googleapis.com/compute/v1/projects/test-project-123456/global/firewalls/firewall-create",
"user": "user@domain.com",
},
"serviceName": "compute.googleapis.com",
},
"receivetimestamp": "2023-05-23 19:19:41.238",
"resource":
{
"labels":
{
"firewall_rule_id": "6563507997690081088",
"project_id": "test-project-123456",
},
"type": "gce_firewall_rule",
},
"severity": "NOTICE",
"timestamp": "2023-05-23 19:19:40.353",
}
- Name: appengine.firewall.update-should-alert
LogType: GCP.AuditLog
ExpectedResult: true
Log:
{
"insertid": "-xxxxxxxxxxxx",
"logname": "projects/test-project-123456/logs/cloudaudit.googleapis.com%2Factivity",
"protopayload":
{
"at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo": { "principalEmail": "user@domain.com" },
"authorizationInfo":
[
{
"granted": true,
"permission": "appengine.applications.update",
"resource": "apps/test-project-123456/firewall/ingressRules/1000",
"resourceAttributes": {},
},
],
"methodName": "google.appengine.v1.Firewall.UpdateIngressRule",
"requestMetadata":
{
"callerIP": "12.12.12.12",
"destinationAttributes": {},
"requestAttributes":
{ "auth": {}, "time": "2023-05-23T19:28:44.663413Z" },
},
"resourceName": "apps/test-project-123456/firewall/ingressRules/1000",
"serviceData":
{
"@type": "type.googleapis.com/google.appengine.v1beta4.AuditData",
},
"serviceName": "appengine.googleapis.com",
"status": {},
},
"receivetimestamp": "2023-05-23 19:28:45.473",
"resource":
{
"labels":
{
"module_id": "",
"project_id": "test-project-123456",
"version_id": "",
"zone": "",
},
"type": "gae_app",
},
"severity": "NOTICE",
"timestamp": "2023-05-23 19:28:44.562",
}
- Name: compute.non-update.firewall.method-should-not-alert
LogType: GCP.AuditLog
ExpectedResult: false
Log: { "methodName": "v1.compute.firewalls.insert" }
- Name: appengine.compute.non-update.firewall.method-should-not-alert
LogType: GCP.AuditLog
ExpectedResult: false
Log: { "methodName": "appengine.compute.v1.Firewall.PatchIngressRule" }
- Name: randomservice.firewall-update.method-should-alert
LogType: GCP.AuditLog
ExpectedResult: true
Log:
{
"protoPayload":
{
"authenticationInfo": { "principalEmail": "user@domain.com" },
"methodName": "randomservice.compute.v1.Firewall.UpdateIngressRule",
"resourceName": "randomservice/test-project-123456/firewall/ingressRules/1000",
"requestMetadata":
{
"callerIP": "12.12.12.12",
"destinationAttributes": {},
"requestAttributes":
{ "auth": {}, "time": "2023-05-23T19:28:44.663413Z" },
},
},
"resource":
{
"labels":
{
"firewall_rule_id": "6563507997690081088",
"project_id": "test-project-123456",
},
"type": "gce_firewall_rule",
},
}
Detection logic
Condition
protoPayload.methodName contains ".Firewall.Update" or protoPayload.methodName contains ".compute.firewalls.patch" or protoPayload.methodName contains ".compute.firewalls.update"
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.
| Field | Kind | Values |
|---|---|---|
protoPayload.methodName | contains |
|
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.
| Field | Source |
|---|---|
project | resource.labels.project_id |
principal | protoPayload.authenticationInfo.principalEmail |
caller_ip | protoPayload.requestMetadata.callerIP |
methodName | protoPayload.methodName |
resourceName | protoPayload.resourceName |
serviceName | protoPayload.serviceName |