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

THREAT-445 Stratus-GCP-Exfiltration #1527

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
8 changes: 7 additions & 1 deletion indexes/alpha-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1036,14 +1036,18 @@
- The Identity and Access Management (IAM) service manages authorization and authentication for a GCP environment. This means that there are very likely multiple privilege escalation methods that use the IAM service and/or its permissions.
- [GCP cloudfunctions functions update](../rules/gcp_audit_rules/gcp_cloudfunctions_functions_update.yml)
- The Identity and Access Management (IAM) service manages authorization and authentication for a GCP environment. This means that there are very likely multiple privilege escalation methods that use the IAM service and/or its permissions.
- [GCP Compute IAM Policy Update Detection](../rules/gcp_audit_rules/gcp_compute_set_iam_policy.yml)
- This rule detects updates to IAM policies for Compute Disks, Images, and Snapshots.
- [GCP compute.instances.create Privilege Escalation](../rules/gcp_audit_rules/gcp_computeinstances_create_privilege_escalation.yml)
- Detects compute.instances.create method for privilege escalation in GCP.
- [GCP Corporate Email Not Used](../rules/gcp_audit_rules/gcp_iam_corp_email.yml)
- A Gmail account is being used instead of a corporate email
- Unexpected domain is being used instead of a corporate email
- [GCP Destructive Queries](../rules/gcp_audit_rules/gcp_destructive_queries.yml)
- Detect any destructive BigQuery queries or jobs such as update, delete, drop, alter or truncate.
- [GCP DNS Zone Modified or Deleted](../rules/gcp_audit_rules/gcp_dns_zone_modified_or_deleted.yml)
- Detection for GCP DNS zones that are deleted, patched, or updated.
- [GCP External User Ownership Invite](../rules/gcp_audit_rules/gcp_invite_external_user_as_owner.yml)
- This rule detects when an external user is invited as an owner of a GCP project using the InsertProjectOwnershipInvite event.
- [GCP Firewall Rule Created](../rules/gcp_audit_rules/gcp_firewall_rule_created.yml)
- This rule detects creations of GCP firewall rules.
- [GCP Firewall Rule Deleted](../rules/gcp_audit_rules/gcp_firewall_rule_deleted.yml)
Expand Down Expand Up @@ -1097,6 +1101,8 @@
- Detects when a service account or key is created manually by a user instead of an automated workflow.
- [GCP serviceusage.apiKeys.create Privilege Escalation](../rules/gcp_audit_rules/gcp_serviceusage_apikeys_create_privilege_escalation.yml)
- Detects serviceusage.apiKeys.create method for privilege escalation in GCP. By default, API Keys are created with no restrictions, which means they have access to the entire GCP project they were created in. We can capitalize on that fact by creating a new API key that may have more privileges than our own user.
- [GCP Snapshot Creation Detection](../rules/gcp_audit_rules/gcp_snapshot_insert.yml)
- This rule detects when someone with an unexpected email domain creates a snapshot of a Compute Disk.
- [GCP SQL Config Changes](../rules/gcp_audit_rules/gcp_sql_config_changes.yml)
- Monitoring changes to Sql Instance configuration may reduce time to detect and correct misconfigurations done on sql server.
- [GCP storage hmac keys create](../rules/gcp_audit_rules/gcp_storage_hmac_keys_create.yml)
Expand Down
2 changes: 1 addition & 1 deletion indexes/detection-coverage.json

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion indexes/gcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,18 @@
- The Identity and Access Management (IAM) service manages authorization and authentication for a GCP environment. This means that there are very likely multiple privilege escalation methods that use the IAM service and/or its permissions.
- [GCP cloudfunctions functions update](../rules/gcp_audit_rules/gcp_cloudfunctions_functions_update.yml)
- The Identity and Access Management (IAM) service manages authorization and authentication for a GCP environment. This means that there are very likely multiple privilege escalation methods that use the IAM service and/or its permissions.
- [GCP Compute IAM Policy Update Detection](../rules/gcp_audit_rules/gcp_compute_set_iam_policy.yml)
- This rule detects updates to IAM policies for Compute Disks, Images, and Snapshots.
- [GCP compute.instances.create Privilege Escalation](../rules/gcp_audit_rules/gcp_computeinstances_create_privilege_escalation.yml)
- Detects compute.instances.create method for privilege escalation in GCP.
- [GCP Corporate Email Not Used](../rules/gcp_audit_rules/gcp_iam_corp_email.yml)
- A Gmail account is being used instead of a corporate email
- Unexpected domain is being used instead of a corporate email
- [GCP Destructive Queries](../rules/gcp_audit_rules/gcp_destructive_queries.yml)
- Detect any destructive BigQuery queries or jobs such as update, delete, drop, alter or truncate.
- [GCP DNS Zone Modified or Deleted](../rules/gcp_audit_rules/gcp_dns_zone_modified_or_deleted.yml)
- Detection for GCP DNS zones that are deleted, patched, or updated.
- [GCP External User Ownership Invite](../rules/gcp_audit_rules/gcp_invite_external_user_as_owner.yml)
- This rule detects when an external user is invited as an owner of a GCP project using the InsertProjectOwnershipInvite event.
- [GCP Firewall Rule Created](../rules/gcp_audit_rules/gcp_firewall_rule_created.yml)
- This rule detects creations of GCP firewall rules.
- [GCP Firewall Rule Deleted](../rules/gcp_audit_rules/gcp_firewall_rule_deleted.yml)
Expand Down Expand Up @@ -85,6 +89,8 @@
- Detects when a service account or key is created manually by a user instead of an automated workflow.
- [GCP serviceusage.apiKeys.create Privilege Escalation](../rules/gcp_audit_rules/gcp_serviceusage_apikeys_create_privilege_escalation.yml)
- Detects serviceusage.apiKeys.create method for privilege escalation in GCP. By default, API Keys are created with no restrictions, which means they have access to the entire GCP project they were created in. We can capitalize on that fact by creating a new API key that may have more privileges than our own user.
- [GCP Snapshot Creation Detection](../rules/gcp_audit_rules/gcp_snapshot_insert.yml)
- This rule detects when someone with an unexpected email domain creates a snapshot of a Compute Disk.
- [GCP SQL Config Changes](../rules/gcp_audit_rules/gcp_sql_config_changes.yml)
- Monitoring changes to Sql Instance configuration may reduce time to detect and correct misconfigurations done on sql server.
- [GCP storage hmac keys create](../rules/gcp_audit_rules/gcp_storage_hmac_keys_create.yml)
Expand Down
3 changes: 3 additions & 0 deletions packs/gcp_audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ PackDefinition:
- GCP.Cloud.Run.Service.Created
- GCP.Cloud.Run.Service.Created.FOLLOWED.BY.Set.IAM.Policy
- GCP.Cloud.Run.Set.IAM.Policy
- GCP.Compute.IAM.Policy.Update
- GCP.Compute.Snapshot.UnexpectedDomain
- GCP.Destructive.Queries
- GCP.DNS.Zone.Modified.or.Deleted
- GCP.Firewall.Rule.Created
Expand All @@ -32,6 +34,7 @@ PackDefinition:
- GCP.Logging.Sink.Modified
- GCP.Permissions.Granted.to.Create.or.Manage.Service.Account.Key
- GCP.Privilege.Escalation.By.Deployments.Create
- GCP.Project.ExternalUserOwnershipInvite
- GCP.Service.Account.Access.Denied
- GCP.Service.Account.or.Keys.Created
- GCP.serviceusage.apiKeys.create.Privilege.Escalation
Expand Down
41 changes: 41 additions & 0 deletions rules/gcp_audit_rules/gcp_compute_set_iam_policy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from panther_gcp_helpers import gcp_alert_context, get_binding_deltas

SUSPICIOUS_ACTIONS = [
"v1.compute.disks.setIamPolicy",
"v1.compute.images.setIamPolicy",
"v1.compute.snapshots.setIamPolicy",
]


def rule(event):
if event.deep_get("protoPayload", "response", "error"):
return False

method = event.deep_get("protoPayload", "methodName", default="METHOD_NOT_FOUND")
if method in SUSPICIOUS_ACTIONS:
return True

return False


def title(event):
actor = event.deep_get(
"protoPayload", "authenticationInfo", "principalEmail", default="<ACTOR_NOT_FOUND>"
)

items = event.deep_get("protoPayload", "methodName", default="ITEMS_NOT_FOUND. ").split(".")[-2]

project = event.deep_get("resource", "labels", "project_id", default="<PROJECT_NOT_FOUND>")
return f"[GCP]: [{actor}] updated IAM policy for [{items}] 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
context["binding_deltas"] = get_binding_deltas(event)
return context
217 changes: 217 additions & 0 deletions rules/gcp_audit_rules/gcp_compute_set_iam_policy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
AnalysisType: rule
DedupPeriodMinutes: 60
DisplayName: GCP Compute IAM Policy Update Detection
Enabled: true
Filename: gcp_compute_set_iam_policy.py
RuleID: "GCP.Compute.IAM.Policy.Update"
Severity: Medium
LogTypes:
- GCP.AuditLog
Description: >
This rule detects updates to IAM policies for Compute Disks, Images, and Snapshots.
Runbook: >
Ensure that the IAM policy update was expected. Unauthorized changes can lead to security risks.
Reference: https://cloud.google.com/compute/docs/access/iam
Tests:
- Name: IAM policy update on a Compute Disk
LogType: GCP.AuditLog
ExpectedResult: true
Log:
{
"insertId": "1abcd23efg456",
"labels": {
"compute.googleapis.com/root_trigger_id": "trigger-id-1"
},
"logName": "projects/test-project/logs/cloudaudit.googleapis.com%2Factivity",
"protoPayload": {
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo": {
"principalEmail": "[email protected]",
"principalSubject": "serviceAccount:[email protected]",
"serviceAccountKeyName": "//iam.googleapis.com/projects/test-project/serviceAccounts/[email protected]/keys/key-id"
},
"authorizationInfo": [
{
"granted": true,
"permission": "compute.disks.setIamPolicy",
"resource": "projects/test-project/zones/us-central1-a/disks/disk-1",
"resourceAttributes": {
"name": "projects/test-project/zones/us-central1-a/disks/disk-1",
"service": "compute",
"type": "compute.disks"
}
}
],
"methodName": "v1.compute.disks.setIamPolicy",
"request": {
"@type": "type.googleapis.com/compute.disks.setIamPolicy",
"policy": {
"bindings": [
{
"members": [
"user:[email protected]"
],
"role": "roles/owner"
}
]
}
},
"requestMetadata": {
"callerIP": "192.0.2.1",
"callerSuppliedUserAgent": "google-cloud-sdk",
"destinationAttributes": {},
"requestAttributes": {
"auth": {},
"time": "2023-10-01T12:34:56.789Z"
}
},
"resourceLocation": {
"currentLocations": [
"us-central1-a"
]
},
"resourceName": "projects/test-project/zones/us-central1-a/disks/disk-1",
"serviceName": "compute.googleapis.com"
},
"receiveTimestamp": "2023-10-01T12:34:57.123Z",
"resource": {
"labels": {
"disk_id": "disk-id-1",
"project_id": "test-project",
"zone": "us-central1-a"
},
"type": "gce_disk"
},
"severity": "NOTICE",
"timestamp": "2023-10-01T12:34:56.789Z"
}
- Name: IAM policy update on a Compute Image
LogType: GCP.AuditLog
ExpectedResult: true
Log:
{
"insertId": "2hijk34lmn789",
"labels": {
"compute.googleapis.com/root_trigger_id": "trigger-id-2"
},
"logName": "projects/test-project/logs/cloudaudit.googleapis.com%2Factivity",
"protoPayload": {
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo": {
"principalEmail": "[email protected]",
"principalSubject": "serviceAccount:[email protected]",
"serviceAccountKeyName": "//iam.googleapis.com/projects/test-project/serviceAccounts/[email protected]/keys/key-id"
},
"authorizationInfo": [
{
"granted": true,
"permission": "compute.images.setIamPolicy",
"resource": "projects/test-project/global/images/image-1",
"resourceAttributes": {
"name": "projects/test-project/global/images/image-1",
"service": "compute",
"type": "compute.images"
}
}
],
"methodName": "v1.compute.images.setIamPolicy",
"request": {
"@type": "type.googleapis.com/compute.images.setIamPolicy",
"policy": {
"bindings": [
{
"members": [
"user:[email protected]"
],
"role": "roles/owner"
}
]
}
},
"requestMetadata": {
"callerIP": "192.0.2.2",
"callerSuppliedUserAgent": "google-cloud-sdk",
"destinationAttributes": {},
"requestAttributes": {
"auth": {},
"time": "2023-10-01T12:45:56.789Z"
}
},
"resourceLocation": {
"currentLocations": [
"us-central1-a"
]
},
"resourceName": "projects/test-project/global/images/image-1",
"serviceName": "compute.googleapis.com"
},
"receiveTimestamp": "2023-10-01T12:45:57.123Z",
"resource": {
"labels": {
"image_id": "image-id-1",
"project_id": "test-project"
},
"type": "gce_image"
},
"severity": "NOTICE",
"timestamp": "2023-10-01T12:45:56.789Z"
}
- Name: Non-IAM policy update on a Compute Disk
LogType: GCP.AuditLog
ExpectedResult: false
Log:
{
"insertId": "4stuv78wxy345",
"labels": {
"compute.googleapis.com/root_trigger_id": "trigger-id-4"
},
"logName": "projects/test-project/logs/cloudaudit.googleapis.com%2Factivity",
"protoPayload": {
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo": {
"principalEmail": "[email protected]",
"principalSubject": "serviceAccount:[email protected]",
"serviceAccountKeyName": "//iam.googleapis.com/projects/test-project/serviceAccounts/[email protected]/keys/key-id"
},
"authorizationInfo": [
{
"granted": true,
"permission": "compute.disks.create",
"resource": "projects/test-project/zones/us-central1-a/disks/disk-2",
"resourceAttributes": {
"name": "projects/test-project/zones/us-central1-a/disks/disk-2",
"service": "compute",
"type": "compute.disks"
}
}
],
"methodName": "v1.compute.disks.create",
"requestMetadata": {
"callerIP": "192.0.2.4",
"callerSuppliedUserAgent": "google-cloud-sdk",
"destinationAttributes": { },
"requestAttributes": {
"auth": { },
"time": "2023-10-01T13:00:00.000Z"
}
},
"resourceLocation": {
"currentLocations": [
"us-central1-a"
]
},
"resourceName": "projects/test-project/zones/us-central1-a/disks/disk-2",
"serviceName": "compute.googleapis.com"
},
"receiveTimestamp": "2023-10-01T13:00:01.000Z",
"resource": {
"labels": {
"disk_id": "disk-id-2",
"project_id": "test-project",
"zone": "us-central1-a"
},
"type": "gce_disk"
},
"severity": "NOTICE",
"timestamp": "2023-10-01T13:00:00.000Z"
}
14 changes: 9 additions & 5 deletions rules/gcp_audit_rules/gcp_iam_corp_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,25 @@ def rule(event):
if not service_data:
return False

# Reference: bit.ly/2WsJdZS
authenticated = event.deep_get(
"protoPayload", "authenticationInfo", "principalEmail", default=""
)
expected_domain = authenticated.split("@")[-1]

binding_deltas = deep_get(service_data, "policyDelta", "bindingDeltas")
if not binding_deltas:
return False

for delta in binding_deltas:
if delta.get("action") != "ADD":
continue
if delta.get("member", "").endswith("@gmail.com"):
return True
return False
if delta.get("member", "").endswith(f"@{expected_domain}"):
return False
return True


def title(event):
return (
f"A GCP IAM account has been created with a Gmail email in "
f"A GCP IAM account has been created with an unexpected email domain in "
f"{event.deep_get('resource', 'labels', 'project_id', default='<UNKNOWN_PROJECT>')}"
)
4 changes: 2 additions & 2 deletions rules/gcp_audit_rules/gcp_iam_corp_email.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Reports:
CIS:
- 1.1
Severity: Low
Description: A Gmail account is being used instead of a corporate email
Description: Unexpected domain is being used instead of a corporate email
Runbook: Remove the user
Reference: https://cloud.google.com/iam/docs/service-account-overview
SummaryAttributes:
Expand Down Expand Up @@ -203,7 +203,7 @@ Tests:
"logName": "projects/western-verve-123456/logs/cloudaudit.googleapis.com%2Factivity",
"receiveTimestamp": "2020-05-15T03:51:35.977314225Z",
}
- Name: Runpanther account added
- Name: Expected account added
ExpectedResult: false
Log:
{
Expand Down
Loading
Loading