From 85df6ca38d87f6cee7de03433cd79f890712b012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Mar=C3=A9chal?= Date: Thu, 26 Mar 2026 14:50:15 +0100 Subject: [PATCH 1/3] New attack technique: Disable VPC Flow Logs on a Subnet (gcp.defense-evasion.remove-vpc-flow-logs) Co-Authored-By: Claude Sonnet 4.6 --- ...cp.defense-evasion.remove-vpc-flow-logs.md | 57 ++++++++ docs/attack-techniques/GCP/index.md | 2 + docs/attack-techniques/list.md | 1 + .../mitre-attack-coverage-matrices.md | 5 +- docs/index.yaml | 7 + .../remove-vpc-flow-logs/main.go | 127 ++++++++++++++++++ .../remove-vpc-flow-logs/main.tf | 52 +++++++ v2/internal/attacktechniques/main.go | 1 + 8 files changed, 250 insertions(+), 2 deletions(-) create mode 100755 docs/attack-techniques/GCP/gcp.defense-evasion.remove-vpc-flow-logs.md create mode 100644 v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs/main.go create mode 100644 v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs/main.tf diff --git a/docs/attack-techniques/GCP/gcp.defense-evasion.remove-vpc-flow-logs.md b/docs/attack-techniques/GCP/gcp.defense-evasion.remove-vpc-flow-logs.md new file mode 100755 index 000000000..063d62dac --- /dev/null +++ b/docs/attack-techniques/GCP/gcp.defense-evasion.remove-vpc-flow-logs.md @@ -0,0 +1,57 @@ +--- +title: Disable VPC Flow Logs on a Subnet +--- + +# Disable VPC Flow Logs on a Subnet + + + idempotent + +Platform: GCP + +## Mappings + +- MITRE ATT&CK + - Defense Evasion + + + +## Description + + +Disables VPC flow logging on a subnet by patching its log configuration. +VPC flow logs record network traffic metadata for all VM instances in a subnet, +providing visibility for network monitoring and forensic investigation. + +Warm-up: + +- Create a VPC network +- Create a subnet with VPC flow logs enabled + +Detonation: + +- Disable VPC flow logs on the subnet by patching its logConfig.enable field to false + +Revert: + +- Re-enable VPC flow logs on the subnet + +References: + +- https://cloud.google.com/vpc/docs/using-flow-logs +- https://cloud.google.com/compute/docs/reference/rest/v1/subnetworks/patch + + +## Instructions + +```bash title="Detonate with Stratus Red Team" +stratus detonate gcp.defense-evasion.remove-vpc-flow-logs +``` +## Detection + + +Identify when VPC flow logging is disabled on a subnet by monitoring for +v1.compute.subnetworks.patch events in GCP Admin Activity audit logs +where the request sets logConfig.enable to false. + + diff --git a/docs/attack-techniques/GCP/index.md b/docs/attack-techniques/GCP/index.md index c4e993e03..832adfc92 100755 --- a/docs/attack-techniques/GCP/index.md +++ b/docs/attack-techniques/GCP/index.md @@ -39,6 +39,8 @@ Note that some Stratus attack techniques may correspond to more than a single AT - [Attempt to Remove a GCP Project from its Organization](./gcp.defense-evasion.remove-project-from-organization.md) + - [Disable VPC Flow Logs on a Subnet](./gcp.defense-evasion.remove-vpc-flow-logs.md) + - [Delete a GCP Log Sink](./gcp.defense-evasion.delete-logging-sink.md) - [Disable a GCP Log Sink](./gcp.defense-evasion.disable-logging-sink.md) diff --git a/docs/attack-techniques/list.md b/docs/attack-techniques/list.md index 82d8c8612..60251ef0d 100755 --- a/docs/attack-techniques/list.md +++ b/docs/attack-techniques/list.md @@ -76,6 +76,7 @@ This page contains the list of all Stratus Attack Techniques. | [Delete a Cloud DNS Logging Policy](./GCP/gcp.defense-evasion.delete-dns-logs.md) | [GCP](./GCP/index.md) | Defense Evasion | | [Disable Data Access Audit Logs for a GCP Service](./GCP/gcp.defense-evasion.disable-audit-logs.md) | [GCP](./GCP/index.md) | Defense Evasion | | [Attempt to Remove a GCP Project from its Organization](./GCP/gcp.defense-evasion.remove-project-from-organization.md) | [GCP](./GCP/index.md) | Defense Evasion | +| [Disable VPC Flow Logs on a Subnet](./GCP/gcp.defense-evasion.remove-vpc-flow-logs.md) | [GCP](./GCP/index.md) | Defense Evasion | | [Enumerate Permissions of a GCP Service Account](./GCP/gcp.discovery.enumerate-permissions.md) | [GCP](./GCP/index.md) | Discovery | | [Exfiltrate Compute Disk by sharing it](./GCP/gcp.exfiltration.share-compute-disk.md) | [GCP](./GCP/index.md) | Exfiltration | | [Exfiltrate Compute Image by sharing it](./GCP/gcp.exfiltration.share-compute-image.md) | [GCP](./GCP/index.md) | Exfiltration | diff --git a/docs/attack-techniques/mitre-attack-coverage-matrices.md b/docs/attack-techniques/mitre-attack-coverage-matrices.md index 57d8a612b..e7ba35a15 100644 --- a/docs/attack-techniques/mitre-attack-coverage-matrices.md +++ b/docs/attack-techniques/mitre-attack-coverage-matrices.md @@ -58,8 +58,9 @@ This provides coverage matrices of MITRE ATT&CK tactics and techniques currently Steal and Use the GCE Default Service Account Token from Outside Google CloudRegister SSH public key to instance metadataCreate an Admin GCP Service AccountDelete a Cloud DNS Logging PolicyRetrieve a High Number of Secret Manager secretsEnumerate Permissions of a GCP Service AccountRegister SSH public key to instance metadataExfiltrate Compute Disk by sharing itCreate a GCE GPU Virtual Machine Backdoor a GCP Service Account through its IAM PolicyCreate a GCP Service Account KeyDisable Data Access Audit Logs for a GCP ServiceSteal and Use the GCE Default Service Account Token from Outside Google CloudExfiltrate Compute Image by sharing itCreate GCE Instances in Multiple Zones Create an Admin GCP Service AccountImpersonate GCP Service AccountsAttempt to Remove a GCP Project from its OrganizationExfiltrate Compute Disk by sharing a snapshot -Create a GCP Service Account KeyDelete a GCP Log Sink -Invite an External User to a GCP ProjectDisable a GCP Log Sink +Create a GCP Service Account KeyDisable VPC Flow Logs on a Subnet +Invite an External User to a GCP ProjectDelete a GCP Log Sink +Disable a GCP Log Sink Reduce Log Retention Period on a Cloud Logging Sink Bucket diff --git a/docs/index.yaml b/docs/index.yaml index 0d2ca4454..14e1bd1f6 100644 --- a/docs/index.yaml +++ b/docs/index.yaml @@ -574,6 +574,13 @@ GCP: - Defense Evasion platform: GCP isIdempotent: true + - id: gcp.defense-evasion.remove-vpc-flow-logs + name: Disable VPC Flow Logs on a Subnet + isSlow: false + mitreAttackTactics: + - Defense Evasion + platform: GCP + isIdempotent: true - id: gcp.defense-evasion.delete-logging-sink name: Delete a GCP Log Sink isSlow: false diff --git a/v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs/main.go b/v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs/main.go new file mode 100644 index 000000000..80fe7c4ed --- /dev/null +++ b/v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs/main.go @@ -0,0 +1,127 @@ +package gcp + +import ( + "context" + _ "embed" + "fmt" + "log" + + compute "cloud.google.com/go/compute/apiv1" + "cloud.google.com/go/compute/apiv1/computepb" + "github.com/datadog/stratus-red-team/v2/pkg/stratus" + "github.com/datadog/stratus-red-team/v2/pkg/stratus/mitreattack" +) + +//go:embed main.tf +var tf []byte + +func init() { + stratus.GetRegistry().RegisterAttackTechnique(&stratus.AttackTechnique{ + ID: "gcp.defense-evasion.remove-vpc-flow-logs", + FriendlyName: "Disable VPC Flow Logs on a Subnet", + Description: ` +Disables VPC flow logging on a subnet by patching its log configuration. +VPC flow logs record network traffic metadata for all VM instances in a subnet, +providing visibility for network monitoring and forensic investigation. + +Warm-up: + +- Create a VPC network +- Create a subnet with VPC flow logs enabled + +Detonation: + +- Disable VPC flow logs on the subnet by patching its logConfig.enable field to false + +Revert: + +- Re-enable VPC flow logs on the subnet + +References: + +- https://cloud.google.com/vpc/docs/using-flow-logs +- https://cloud.google.com/compute/docs/reference/rest/v1/subnetworks/patch +`, + Detection: ` +Identify when VPC flow logging is disabled on a subnet by monitoring for +v1.compute.subnetworks.patch events in GCP Admin Activity audit logs +where the request sets logConfig.enable to false. +`, + Platform: stratus.GCP, + IsIdempotent: true, + MitreAttackTactics: []mitreattack.Tactic{mitreattack.DefenseEvasion}, + PrerequisitesTerraformCode: tf, + Detonate: detonate, + Revert: revert, + }) +} + +func setFlowLogsEnabled(providers stratus.CloudProviders, subnetName string, region string, enabled bool) error { + gcp := providers.GCP() + ctx := context.Background() + projectId := gcp.GetProjectId() + + subnetsClient, err := compute.NewSubnetworksRESTClient(ctx, gcp.Options()) + if err != nil { + return fmt.Errorf("failed to create subnetworks client: %w", err) + } + defer subnetsClient.Close() + + subnet, err := subnetsClient.Get(ctx, &computepb.GetSubnetworkRequest{ + Project: projectId, + Region: region, + Subnetwork: subnetName, + }) + if err != nil { + return fmt.Errorf("failed to get subnet %s: %w", subnetName, err) + } + + op, err := subnetsClient.Patch(ctx, &computepb.PatchSubnetworkRequest{ + Project: projectId, + Region: region, + Subnetwork: subnetName, + SubnetworkResource: &computepb.Subnetwork{ + Fingerprint: subnet.Fingerprint, + LogConfig: &computepb.SubnetworkLogConfig{ + Enable: ptr(enabled), + }, + }, + }) + if err != nil { + return fmt.Errorf("failed to patch subnet %s: %w", subnetName, err) + } + + if err = op.Wait(ctx); err != nil { + return fmt.Errorf("failed waiting for subnet patch to complete: %w", err) + } + + return nil +} + +func detonate(params map[string]string, providers stratus.CloudProviders) error { + subnetName := params["subnet_name"] + region := params["region"] + + log.Printf("Disabling VPC flow logs on subnet %s in region %s\n", subnetName, region) + if err := setFlowLogsEnabled(providers, subnetName, region, false); err != nil { + return err + } + log.Printf("Successfully disabled VPC flow logs on subnet %s\n", subnetName) + return nil +} + +func revert(params map[string]string, providers stratus.CloudProviders) error { + subnetName := params["subnet_name"] + region := params["region"] + + log.Printf("Re-enabling VPC flow logs on subnet %s in region %s\n", subnetName, region) + if err := setFlowLogsEnabled(providers, subnetName, region, true); err != nil { + return err + } + log.Printf("Successfully re-enabled VPC flow logs on subnet %s\n", subnetName) + return nil +} + +func ptr[T any](v T) *T { + return &v +} diff --git a/v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs/main.tf b/v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs/main.tf new file mode 100644 index 000000000..63e40e0f7 --- /dev/null +++ b/v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs/main.tf @@ -0,0 +1,52 @@ +terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "~> 6.18.1" + } + random = { + source = "hashicorp/random" + version = "~> 3.3.2" + } + } +} + +locals { + resource_prefix = "stratus-red-team-rvfl" # stratus red team remove vpc flow logs +} + +resource "random_string" "suffix" { + length = 8 + special = false + min_lower = 8 +} + +resource "google_compute_network" "vpc" { + name = "${local.resource_prefix}-vpc-${random_string.suffix.result}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "subnet" { + name = "${local.resource_prefix}-subnet-${random_string.suffix.result}" + ip_cidr_range = "10.10.0.0/24" + region = "us-central1" + network = google_compute_network.vpc.id + + log_config { + aggregation_interval = "INTERVAL_5_SEC" + flow_sampling = 0.5 + metadata = "INCLUDE_ALL_METADATA" + } +} + +output "subnet_name" { + value = google_compute_subnetwork.subnet.name +} + +output "region" { + value = google_compute_subnetwork.subnet.region +} + +output "display" { + value = format("Subnet %s in region %s with VPC flow logs enabled", google_compute_subnetwork.subnet.name, google_compute_subnetwork.subnet.region) +} diff --git a/v2/internal/attacktechniques/main.go b/v2/internal/attacktechniques/main.go index 62a758fee..f3a1804c9 100644 --- a/v2/internal/attacktechniques/main.go +++ b/v2/internal/attacktechniques/main.go @@ -71,6 +71,7 @@ import ( _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/defense-evasion/disable-logging-sink" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/defense-evasion/reduce-sink-log-retention" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/defense-evasion/remove-project-from-organization" + _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/discovery/enumerate-permissions" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/exfiltration/share-compute-disk" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/exfiltration/share-compute-image" From f63b19a9b5dd42ddaf0cabaf10863b66dbbe8c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Mar=C3=A9chal?= Date: Mon, 30 Mar 2026 14:42:42 +0200 Subject: [PATCH 2/3] Add external references for technique documentation Co-Authored-By: Claude Opus 4.6 (1M context) --- .../gcp/defense-evasion/remove-vpc-flow-logs/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs/main.go b/v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs/main.go index 80fe7c4ed..ae90f586f 100644 --- a/v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs/main.go +++ b/v2/internal/attacktechniques/gcp/defense-evasion/remove-vpc-flow-logs/main.go @@ -41,6 +41,8 @@ References: - https://cloud.google.com/vpc/docs/using-flow-logs - https://cloud.google.com/compute/docs/reference/rest/v1/subnetworks/patch +- https://github.com/GoogleCloudPlatform/security-analytics/blob/main/src/3.02/3.02.md +- https://securitylabs.datadoghq.com/cloud-security-atlas/attacks/removing-vpc-flow-logs/ `, Detection: ` Identify when VPC flow logging is disabled on a subnet by monitoring for From 0949c0a0b380331cc3dc385491cb00214aaf90e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Mar=C3=A9chal?= Date: Wed, 1 Apr 2026 10:40:14 +0200 Subject: [PATCH 3/3] Address PR feedback: remove HackTricks refs, regenerate docs Co-Authored-By: Claude Opus 4.6 (1M context) --- .../GCP/gcp.defense-evasion.remove-vpc-flow-logs.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/attack-techniques/GCP/gcp.defense-evasion.remove-vpc-flow-logs.md b/docs/attack-techniques/GCP/gcp.defense-evasion.remove-vpc-flow-logs.md index 063d62dac..6dcfdc45f 100755 --- a/docs/attack-techniques/GCP/gcp.defense-evasion.remove-vpc-flow-logs.md +++ b/docs/attack-techniques/GCP/gcp.defense-evasion.remove-vpc-flow-logs.md @@ -40,6 +40,8 @@ References: - https://cloud.google.com/vpc/docs/using-flow-logs - https://cloud.google.com/compute/docs/reference/rest/v1/subnetworks/patch +- https://github.com/GoogleCloudPlatform/security-analytics/blob/main/src/3.02/3.02.md +- https://securitylabs.datadoghq.com/cloud-security-atlas/attacks/removing-vpc-flow-logs/ ## Instructions