Mature security operations teams have an established process to control how changes are made to detection content running in their security tools. For example, if an organization has implemented Detection-as-Code to ensure that all proposed changes to detection content are tested, reviewed, and approved, the security team must be able to detect unexpected/unauthorized changes that are made outside of their defined process and have the capability to roll back changes quickly & reliably.
A seemingly innocuous tweak to a rule could result in a flood of false positives or worse, missed opportunities to detect and respond to threats early on before they can cause significant damage. In this series, I’ll demonstrate two methods for detecting changes made to rules in Google Security Operations (SecOps), as well as how to filter out expected behavior. Part one will walk through how to detect rule changes using Google SecOps. Part two will show how to alert on rule changes by configuring Google Cloud Monitoring.
Exploring Audit Logs for Google SecOps
Google SecOps writes audit logs to record who did what, when, and where within the platform. For example, an event is logged when a user modifies a YARA-L rule in the rules editor or via Google SecOps’ REST API. These Cloud Audit Logs are accessible in the Google Cloud console for the project that’s linked to your Google SecOps tenant. The logs can also be ingested into Google SecOps so that they can be used with searches and rules.
Please note, this post assumes that you’ve completed the steps to bind your Google Cloud project to your Google SecOps tenant and configured feature access control using IAM. Please reference the onboarding or migrating a Google SecOps instance documentation for guidance and reach out to your support representative if you require any additional assistance.
As a prerequisite to ingesting these audit logs into Google SecOps, let’s briefly explore them by running a couple of queries in Logs Explorer in the Google Cloud console. According to the documentation, the Google Cloud service name, chronicle.googleapis.com writes audit log events for operations related to detection rules.
The following query can be used in Logs Explorer to search for events written by the chronicle.googleapis.com service.
resource.type="audited_resource"
resource.labels.service="chronicle.googleapis.com"
The query below returned 198 results. There are six results associated with the “RuleService.UpdateRule” API method. We’re on the right track to verifying what events are logged when rules are modified in Google SecOps.
Reviewing Google SecOps audit logs in Logs Explorer
To better understand the audit logs that are written by Google SecOps, I carried out specific actions in the rules editor in my Google SecOps tenant and analyzed the events that were generated in Logs Explorer. The query below searches for any rule change attempts (allowed/denied) that have occurred in SecOps and includes comments to explain each event.
resource.type="audited_resource"
resource.labels.service="chronicle.googleapis.com"
protoPayload.methodName=(
-- Attempts to create a rule
"google.cloud.chronicle.v1alpha.RuleService.CreateRule" OR
-- Attempts to create a new version of a rule
"google.cloud.chronicle.v1alpha.RuleService.UpdateRule" OR
-- Attempts to update the deployment state of a rule (enable, disable, archive, run frequency, etc)
"google.cloud.chronicle.v1alpha.RuleService.UpdateRuleDeployment" OR
-- Attempts to delete a rule
"google.cloud.chronicle.v1alpha.RuleService.DeleteRule"
)
The sample audit log event below shows that a user successfully updated a rule in Google SecOps. The event contains the unique ID of the rule that was updated as well as the new content of the YARA-L rule under the “text” field. The event contains other useful information such as the source IP address for the user and the rule’s deployment state.
Reviewing a Google SecOps audit log event after modifying a rule
Ingesting Google Cloud Audit Logs into Google SecOps
In this post, we’re going to create a YARA-L rule that detects rule changes in Google SecOps. Before we can do that, we need to enable the ingestion of Google Cloud Audit logs into Google SecOps. This is accomplished in the Google Cloud console on the “Google Security Operations administration settings” page. Select the Google Cloud organization that contains the project that’s bound to your Google SecOps tenant and enable the options highlighted in the image below.
Enabling the ingestion of Google Cloud Audit logs into Google SecOps
Running the following UDM search validates that audit log events for rule changes are being ingested successfully into Google SecOps. You might be wondering, what events are logged when a rule is live enabled/disabled, archived, or its run frequency is changed? These events are logged under the “RuleService.UpdateRuleDeployment” event type included in the UDM search below.
metadata.log_type = "GCP_CLOUDAUDIT"
(
metadata.product_event_type = "google.cloud.chronicle.v1alpha.RuleService.CreateRule" OR
metadata.product_event_type = "google.cloud.chronicle.v1alpha.RuleService.UpdateRule" OR
metadata.product_event_type = "google.cloud.chronicle.v1alpha.RuleService.UpdateRuleDeployment" OR
metadata.product_event_type = "google.cloud.chronicle.v1alpha.RuleService.DeleteRule"
)
Searching for rule change events
Detecting Rule Changes
Now that we understand what events are logged when rule changes happen in Google SecOps and are ingesting those events, let’s create a rule that alerts on this behavior.
The YARA-L rule below detects when a rule is successfully created, updated, deleted, archived, enabled, disabled, and so on.
rule google_secops_rule_modified_or_deleted {
meta:
author = "Google Cloud Security"
description = "Detects changes to rules in Google SecOps."
assumption = "Google SecOps is ingesting Google Cloud logs. Reference: https://cloud.google.com/chronicle/docs/ingestion/cloud/ingest-gcp-logs"
type = "alert"
severity = "Info"
priority = "Info"
platform = "Google SecOps"
data_source = "gcp cloud audit"
events:
$secops.metadata.vendor_name = "Google Cloud Platform"
$secops.metadata.product_name = "Google Cloud Platform"
$secops.metadata.product_event_type = /google\\.cloud\\.chronicle\\..*\\.RuleService\\.(CreateRule|UpdateRule|UpdateRuleDeployment|DeleteRule)/
$secops.security_result.action = "ALLOW"
$secops.principal.user.userid = $userid
match:
$userid over 30m
outcome:
$risk_score = max(10)
$product_event_type = array_distinct($secops.metadata.product_event_type)
$security_result_summary = array_distinct($secops.security_result.action)
$event_count = count_distinct($secops.metadata.id)
$target_resource_name = array_distinct($secops.target.resource.name)
$principal_user_userid = array_distinct($secops.principal.user.userid)
$principal_ip = array_distinct($secops.principal.ip)
$principal_ip_country = array_distinct($secops.principal.ip_geo_artifact.location.country_or_region)
$principal_ip_state = array_distinct($secops.principal.ip_geo_artifact.location.state)
$principal_ip_city = array_distinct($secops.principal.location.city)
condition:
$secops
}
Our next logical step is to test the new rule. The results below confirm that the rule detects when rules are modified or deleted in Google SecOps.
Testing the YARA-L rule
Reviewing one of the detections tells me that the service account, “chronicle-api” deleted a rule with the unique ID of “ru_30bc5c68-b6a9-45a6-8cdb-0fee5a3a4a14”.
Reviewing a detection generated by the YARA-L rule
In my environment, I use a service account to manage rules programmatically via Google SecOps’ REST API. For today’s example, let’s assume that rule changes made by this service account in our Detection-as-Code pipeline are considered authorized activity and can be filtered out from our detection logic. Changes made by other accounts may be suspicious and should be verified by the security team.
Adding the following line to the end of the “events” section of the YARA-L rule filters out rule modification/deletion activity from the service account, “chronicle-api@xxx-xxx.iam.gserviceaccount.com”
$userid != "chronicle-api@xxx-xxx.iam.gserviceaccount.com"
Following best practices, I tested the rule again after making changes to ensure it matches on the intended behavior. Things are looking good – detections are no longer generated by rule changes made by the above service account.
Testing the YARA-L rule after filtering out expected behavior
Wrap Up
That’s it for part one where I covered the following:
- Querying Google SecOps’ audit logs in Logs Explorer within the Google Cloud console
- Ingesting Google Cloud logs into Google SecOps
- Creating and testing a YARA-L rule that detects when changes are made to rules in Google SecOps
Thanks for reading. Join me in part two where I’ll discuss another technique for detecting this behavior using Google Cloud Monitoring.