diff --git a/docs/attack-techniques/GCP/gcp.exfiltration.open-port-22-ingress.md b/docs/attack-techniques/GCP/gcp.exfiltration.open-port-22-ingress.md new file mode 100755 index 000000000..10375e3e0 --- /dev/null +++ b/docs/attack-techniques/GCP/gcp.exfiltration.open-port-22-ingress.md @@ -0,0 +1,63 @@ +--- +title: Open Ingress Port 22 on a Firewall Rule +--- + +# Open Ingress Port 22 on a Firewall Rule + + + + +Platform: GCP + +## Mappings + +- MITRE ATT&CK + - Exfiltration + + + +## Description + + +Creates a GCP firewall rule that opens ingress TCP port 22 (SSH) to the world +(0.0.0.0/0) on a VPC network. + +An attacker who has compromised a GCP environment may create such a rule to +establish SSH access to any VM instance in the affected network, or to exfiltrate +data by tunnelling traffic over SSH. + +Warm-up: + +- Create a VPC network + +Detonation: + +- Create a firewall rule named <vpc>-allow-ssh that allows TCP:22 ingress + from 0.0.0.0/0 + +Revert: + +- Delete the firewall rule + +References: + +- https://cloud.google.com/vpc/docs/firewalls +- https://cloud.google.com/compute/docs/reference/rest/v1/firewalls/insert +- https://unit42.paloaltonetworks.com/cloud-virtual-machine-attack-vectors/ +- https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/CloudVPC/unrestricted-ssh-access.html + + +## Instructions + +```bash title="Detonate with Stratus Red Team" +stratus detonate gcp.exfiltration.open-port-22-ingress +``` +## Detection + + +Identify when a firewall rule opening a sensitive port to the world is created by +monitoring for v1.compute.firewalls.insert events in GCP Admin Activity +audit logs where sourceRanges includes 0.0.0.0/0 and +allowed[].ports contains port 22. + + diff --git a/docs/attack-techniques/GCP/index.md b/docs/attack-techniques/GCP/index.md index 71df890ce..049274801 100755 --- a/docs/attack-techniques/GCP/index.md +++ b/docs/attack-techniques/GCP/index.md @@ -82,6 +82,8 @@ Note that some Stratus attack techniques may correspond to more than a single AT ## Exfiltration + - [Open Ingress Port 22 on a Firewall Rule](./gcp.exfiltration.open-port-22-ingress.md) + - [Exfiltrate Compute Disk by sharing it](./gcp.exfiltration.share-compute-disk.md) - [Exfiltrate Compute Image by sharing it](./gcp.exfiltration.share-compute-image.md) diff --git a/docs/attack-techniques/list.md b/docs/attack-techniques/list.md index 9d520b47c..31780c8d5 100755 --- a/docs/attack-techniques/list.md +++ b/docs/attack-techniques/list.md @@ -80,6 +80,7 @@ This page contains the list of all Stratus Attack Techniques. | [Read GCE Instance Metadata via the Compute API](./GCP/gcp.discovery.download-instance-metadata.md) | [GCP](./GCP/index.md) | Discovery | | [Enumerate Permissions of a GCP Service Account](./GCP/gcp.discovery.enumerate-permissions.md) | [GCP](./GCP/index.md) | Discovery | | [Modify a GCE Instance Startup Script](./GCP/gcp.execution.modify-gce-startup-script.md) | [GCP](./GCP/index.md) | Execution, Privilege Escalation | +| [Open Ingress Port 22 on a Firewall Rule](./GCP/gcp.exfiltration.open-port-22-ingress.md) | [GCP](./GCP/index.md) | Exfiltration | | [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 | | [Exfiltrate Compute Disk by sharing a snapshot](./GCP/gcp.exfiltration.share-compute-snapshot.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 88a75d9f3..f63941556 100644 --- a/docs/attack-techniques/mitre-attack-coverage-matrices.md +++ b/docs/attack-techniques/mitre-attack-coverage-matrices.md @@ -55,11 +55,11 @@ This provides coverage matrices of MITRE ATT&CK tactics and techniques currently
- - - - - + + + + + diff --git a/docs/index.yaml b/docs/index.yaml index b7678ff69..cb08a49c3 100644 --- a/docs/index.yaml +++ b/docs/index.yaml @@ -642,6 +642,13 @@ GCP: platform: GCP isIdempotent: false Exfiltration: + - id: gcp.exfiltration.open-port-22-ingress + name: Open Ingress Port 22 on a Firewall Rule + isSlow: false + mitreAttackTactics: + - Exfiltration + platform: GCP + isIdempotent: false - id: gcp.exfiltration.share-compute-disk name: Exfiltrate Compute Disk by sharing it isSlow: false diff --git a/v2/internal/attacktechniques/gcp/exfiltration/open-port-22-ingress/main.go b/v2/internal/attacktechniques/gcp/exfiltration/open-port-22-ingress/main.go new file mode 100644 index 000000000..9db99db12 --- /dev/null +++ b/v2/internal/attacktechniques/gcp/exfiltration/open-port-22-ingress/main.go @@ -0,0 +1,138 @@ +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.exfiltration.open-port-22-ingress", + FriendlyName: "Open Ingress Port 22 on a Firewall Rule", + Description: ` +Creates a GCP firewall rule that opens ingress TCP port 22 (SSH) to the world +(0.0.0.0/0) on a VPC network. + +An attacker who has compromised a GCP environment may create such a rule to +establish SSH access to any VM instance in the affected network, or to exfiltrate +data by tunnelling traffic over SSH. + +Warm-up: + +- Create a VPC network + +Detonation: + +- Create a firewall rule named <vpc>-allow-ssh that allows TCP:22 ingress + from 0.0.0.0/0 + +Revert: + +- Delete the firewall rule + +References: + +- https://cloud.google.com/vpc/docs/firewalls +- https://cloud.google.com/compute/docs/reference/rest/v1/firewalls/insert +- https://unit42.paloaltonetworks.com/cloud-virtual-machine-attack-vectors/ +- https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/CloudVPC/unrestricted-ssh-access.html +`, + Detection: ` +Identify when a firewall rule opening a sensitive port to the world is created by +monitoring for v1.compute.firewalls.insert events in GCP Admin Activity +audit logs where sourceRanges includes 0.0.0.0/0 and +allowed[].ports contains port 22. +`, + Platform: stratus.GCP, + IsIdempotent: false, + MitreAttackTactics: []mitreattack.Tactic{mitreattack.Exfiltration}, + PrerequisitesTerraformCode: tf, + Detonate: detonate, + Revert: revert, + }) +} + +func detonate(params map[string]string, providers stratus.CloudProviders) error { + gcp := providers.GCP() + projectId := gcp.GetProjectId() + vpcName := params["vpc_name"] + ctx := context.Background() + + client, err := compute.NewFirewallsRESTClient(ctx, gcp.Options()) + if err != nil { + return fmt.Errorf("failed to create firewalls client: %w", err) + } + defer client.Close() + + firewallName := vpcName + "-allow-ssh" + log.Printf("Creating firewall rule %s allowing TCP:22 from 0.0.0.0/0 on VPC %s\n", firewallName, vpcName) + op, err := client.Insert(ctx, &computepb.InsertFirewallRequest{ + Project: projectId, + FirewallResource: &computepb.Firewall{ + Name: ptr(firewallName), + Network: ptr(fmt.Sprintf("projects/%s/global/networks/%s", projectId, vpcName)), + Direction: ptr("INGRESS"), + Allowed: []*computepb.Allowed{ + { + IPProtocol: ptr("tcp"), + Ports: []string{"22"}, + }, + }, + SourceRanges: []string{"0.0.0.0/0"}, + }, + }) + if err != nil { + return fmt.Errorf("failed to create firewall rule: %w", err) + } + + if err = op.Wait(ctx); err != nil { + return fmt.Errorf("failed waiting for firewall rule creation: %w", err) + } + + log.Printf("Successfully created firewall rule %s\n", firewallName) + return nil +} + +func revert(params map[string]string, providers stratus.CloudProviders) error { + gcp := providers.GCP() + projectId := gcp.GetProjectId() + vpcName := params["vpc_name"] + ctx := context.Background() + + client, err := compute.NewFirewallsRESTClient(ctx, gcp.Options()) + if err != nil { + return fmt.Errorf("failed to create firewalls client: %w", err) + } + defer client.Close() + + firewallName := vpcName + "-allow-ssh" + log.Printf("Deleting firewall rule %s\n", firewallName) + op, err := client.Delete(ctx, &computepb.DeleteFirewallRequest{ + Project: projectId, + Firewall: firewallName, + }) + if err != nil { + return fmt.Errorf("failed to delete firewall rule: %w", err) + } + + if err = op.Wait(ctx); err != nil { + return fmt.Errorf("failed waiting for firewall rule deletion: %w", err) + } + + log.Printf("Successfully deleted firewall rule %s\n", firewallName) + return nil +} + +func ptr[T any](v T) *T { + return &v +} diff --git a/v2/internal/attacktechniques/gcp/exfiltration/open-port-22-ingress/main.tf b/v2/internal/attacktechniques/gcp/exfiltration/open-port-22-ingress/main.tf new file mode 100644 index 000000000..fc083749b --- /dev/null +++ b/v2/internal/attacktechniques/gcp/exfiltration/open-port-22-ingress/main.tf @@ -0,0 +1,35 @@ +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-opi22" # open port ingress 22 +} + +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 +} + +output "vpc_name" { + value = google_compute_network.vpc.name +} + +output "display" { + value = format("VPC network %s", google_compute_network.vpc.name) +} diff --git a/v2/internal/attacktechniques/main.go b/v2/internal/attacktechniques/main.go index 5813c9b4e..48c792fb1 100644 --- a/v2/internal/attacktechniques/main.go +++ b/v2/internal/attacktechniques/main.go @@ -78,6 +78,7 @@ import ( _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/execution/modify-vertex-notebook-startup" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/execution/os-config-run-command" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/exfiltration/backdoor-gcs-bucket" + _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/exfiltration/open-port-22-ingress" _ "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" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/exfiltration/share-compute-snapshot"
Initial AccessExecutionPersistencePrivilege EscalationDefense EvasionCredential AccessDiscoveryLateral MovementExfiltrationImpact
Steal and Use the GCE Default Service Account Token from Outside Google CloudModify a GCE Instance Startup ScriptRegister SSH public key to instance metadataModify a GCE Instance Startup ScriptDelete a Cloud DNS Logging PolicyRetrieve a High Number of Secret Manager secretsRead GCE Instance Metadata via the Compute APIRegister SSH public key to instance metadataExfiltrate Compute Disk by sharing itCreate a GCE GPU Virtual Machine
Inject a Malicious Startup Script into a Vertex AI Workbench InstanceBackdoor a GCP Service Account through its IAM PolicyCreate an Admin GCP Service AccountDisable Data Access Audit Logs for a GCP ServiceSteal and Use the GCE Default Service Account Token from Outside Google CloudEnumerate Permissions of a GCP Service AccountExfiltrate Compute Image by sharing itCreate GCE Instances in Multiple Zones
Execute Commands on GCE Instances via OS Config AgentCreate an Admin GCP Service AccountCreate a GCP Service Account KeyAttempt to Remove a GCP Project from its OrganizationExfiltrate Compute Disk by sharing a snapshot
Create a GCP Service Account KeyImpersonate GCP Service AccountsDisable VPC Flow Logs on a SubnetBackdoor a GCS Bucket via Overly Permissive IAM Policy
Invite an External User to a GCP ProjectInject a Malicious Startup Script into a Vertex AI Workbench InstanceDelete a GCP Log Sink
Steal and Use the GCE Default Service Account Token from Outside Google CloudModify a GCE Instance Startup ScriptRegister SSH public key to instance metadataModify a GCE Instance Startup ScriptDelete a Cloud DNS Logging PolicyRetrieve a High Number of Secret Manager secretsRead GCE Instance Metadata via the Compute APIRegister SSH public key to instance metadataOpen Ingress Port 22 on a Firewall RuleCreate a GCE GPU Virtual Machine
Inject a Malicious Startup Script into a Vertex AI Workbench InstanceBackdoor a GCP Service Account through its IAM PolicyCreate an Admin GCP Service AccountDisable Data Access Audit Logs for a GCP ServiceSteal and Use the GCE Default Service Account Token from Outside Google CloudEnumerate Permissions of a GCP Service AccountExfiltrate Compute Disk by sharing itCreate GCE Instances in Multiple Zones
Execute Commands on GCE Instances via OS Config AgentCreate an Admin GCP Service AccountCreate a GCP Service Account KeyAttempt to Remove a GCP Project from its OrganizationExfiltrate Compute Image by sharing it
Create a GCP Service Account KeyImpersonate GCP Service AccountsDisable VPC Flow Logs on a SubnetExfiltrate Compute Disk by sharing a snapshot
Invite an External User to a GCP ProjectInject a Malicious Startup Script into a Vertex AI Workbench InstanceDelete a GCP Log SinkBackdoor a GCS Bucket via Overly Permissive IAM Policy
Disable a GCP Log Sink
Reduce Log Retention Period on a Cloud Logging Sink Bucket