diff --git a/docs/attack-techniques/GCP/gcp.exfiltration.sql-export-bucket.md b/docs/attack-techniques/GCP/gcp.exfiltration.sql-export-bucket.md
new file mode 100644
index 000000000..824a7c4f3
--- /dev/null
+++ b/docs/attack-techniques/GCP/gcp.exfiltration.sql-export-bucket.md
@@ -0,0 +1,120 @@
+---
+title: Exporting Cloud SQL database to Storage bucket
+---
+
+# Exporting Cloud SQL database to Storage bucket
+
+slow
+
+idempotent
+
+Platform: GCP
+
+## MITRE ATT&CK Tactics
+
+
+- Exfiltration
+
+## Description
+
+
+Exfiltrates data from a Cloud SQL database by exporting to internal storage bucket.
+
+Warm-up:
+
+- Create a Cloud SQL instance
+- Create a storage bucket and grant objectAdmin to Cloud SQL instance
+- Populate the database
+
+Detonation:
+
+- Export the database into the storage bucket
+
+!!! info
+
+ Provisioning the Cloud SQL requires a few minutes.
+
+Reference:
+
+- https://cloud.google.com/sdk/gcloud/reference/sql/export/sql
+- https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.html
+
+
+
+## Instructions
+
+```bash title="Detonate with Stratus Red Team"
+stratus detonate gcp.exfiltration.sql-export-bucket
+```
+
+
+## Detection
+
+Exporting the database is detected as 'cloudsql.instances.export' in Cloud Logging.
+
+Data Access logging for Cloud SQL instance is disabled by default, thus we need to enable it (if not enabled).
+
+- Go to "IAM & Admin" -> "Audit Logs"
+- Locate "Cloud SQL"
+- on "Permission Types", check the "Admin read"
+
+You can use following query to filter the events:
+
+```
+resource.type="cloudsql_database"
+protoPayload.serviceName="cloudsql.googleapis.com"
+protoPayload.methodName="cloudsql.instances.export"
+```
+
+Sample event (shortened for readability):
+
+```json
+{
+ "logName": "projects/my-project-id/logs/cloudaudit.googleapis.com%2Factivity",
+ "protoPayload": {
+ "authenticationInfo": {
+ "principalEmail": "username@service.com",
+ },
+ "methodName": "cloudsql.instances.export",
+ "request": {
+ @type: "type.googleapis.com/google.cloud.sql.v1.SqlInstancesExportRequest",
+ "body": {
+ "exportContext": {
+ "databases": [
+ "stratus-db"
+ ],
+ "fileType": "SQL",
+ "uri": "gs://my-bucket-id/dump.sql.gz"
+ }
+ },
+ "instance": "my-cloudsql-instance-id",
+ }
+ "resourceName": "projects/my-project-id/instances/my-cloudsql-instance-id",
+ "serviceName": "cloudsql.googleapis.com",
+ },
+ "resource": {
+ "type": "cloudsql_database"
+ },
+ "severity": "INFO"
+}
+```
+
+subsequently, detect the 'storage.objects.create' event for creating the object on bucket.
+
+```json
+{
+ "logName": "projects/my-project-id/logs/cloudaudit.googleapis.com%2Factivity",
+ "protoPayload": {
+ "authenticationInfo": {
+ "principalEmail": "username@service.com",
+ },
+ "methodName": "storage.objects.create",
+ "resourceName": "projects/_/buckets/my-bucket-id/objects/dump.sql.gz",
+ "serviceName": "cloudsql.googleapis.com",
+ },
+ "resource": {
+ "type": "gcs_bucket"
+ },
+ "severity": "INFO"
+}
+```
\ No newline at end of file
diff --git a/docs/attack-techniques/GCP/index.md b/docs/attack-techniques/GCP/index.md
index ed24cbaa2..3a736041f 100755
--- a/docs/attack-techniques/GCP/index.md
+++ b/docs/attack-techniques/GCP/index.md
@@ -17,6 +17,8 @@ Note that some Stratus attack techniques may correspond to more than a single AT
- [Exfiltrate Compute Disk by sharing a snapshot](./gcp.exfiltration.share-compute-snapshot.md)
+- [Exporting Cloud SQL database to Storage bucket](./gcp.exfiltration.sql-export-bucket.md)
+
## Persistence
diff --git a/docs/attack-techniques/list.md b/docs/attack-techniques/list.md
index 589adb942..0f2c321e3 100755
--- a/docs/attack-techniques/list.md
+++ b/docs/attack-techniques/list.md
@@ -67,6 +67,7 @@ This page contains the list of all Stratus Attack Techniques.
| [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 |
+| [Exporting Cloud SQL database to Storage bucket](./GCP/gcp.exfiltration.sql-export-bucket.md) | [GCP](./GCP/index.md) | Exfiltration |
| [Backdoor a GCP Service Account through its IAM Policy](./GCP/gcp.persistence.backdoor-service-account-policy.md) | [GCP](./GCP/index.md) | Persistence |
| [Create an Admin GCP Service Account](./GCP/gcp.persistence.create-admin-service-account.md) | [GCP](./GCP/index.md) | Persistence, Privilege Escalation |
| [Create a GCP Service Account Key](./GCP/gcp.persistence.create-service-account-key.md) | [GCP](./GCP/index.md) | Persistence, Privilege Escalation |
diff --git a/docs/index.yaml b/docs/index.yaml
index 742095b6d..98ad2b0e0 100644
--- a/docs/index.yaml
+++ b/docs/index.yaml
@@ -415,6 +415,13 @@ GCP:
- Exfiltration
platform: GCP
isIdempotent: true
+ - id: gcp.exfiltration.sql-export-bucket
+ name: Exporting Cloud SQL database to Storage bucket
+ isSlow: true
+ mitreAttackTactics:
+ - Exfiltration
+ platform: GCP
+ isIdempotent: true
Persistence:
- id: gcp.persistence.backdoor-service-account-policy
name: Backdoor a GCP Service Account through its IAM Policy
diff --git a/v2/internal/attacktechniques/gcp/exfiltration/sql-export-bucket/main.go b/v2/internal/attacktechniques/gcp/exfiltration/sql-export-bucket/main.go
new file mode 100644
index 000000000..44eb5b00c
--- /dev/null
+++ b/v2/internal/attacktechniques/gcp/exfiltration/sql-export-bucket/main.go
@@ -0,0 +1,172 @@
+package gcp
+
+import (
+ "context"
+ _ "embed"
+ "fmt"
+ "log"
+ "time"
+ "google.golang.org/api/sqladmin/v1"
+ "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() {
+ const CodeBlock = "```"
+ const AttackTechniqueId = "gcp.exfiltration.sql-export-bucket"
+
+ stratus.GetRegistry().RegisterAttackTechnique(&stratus.AttackTechnique{
+ ID: AttackTechniqueId,
+ FriendlyName: "Exporting Cloud SQL database to Storage bucket",
+ Description: `
+Exfiltrates data from a Cloud SQL database by exporting to internal storage bucket.
+
+Warm-up:
+
+- Create a Cloud SQL instance
+- Create a storage bucket and grant objectAdmin to Cloud SQL instance
+- Populate the database
+
+Detonation:
+
+- Export the database into the storage bucket
+
+!!! info
+
+ Provisioning the Cloud SQL requires a few minutes.
+
+Reference:
+
+- https://cloud.google.com/sdk/gcloud/reference/sql/export/sql
+- https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.html
+`,
+ Detection: `
+Exporting the database is detected as 'cloudsql.instances.export' in Cloud Logging.
+
+Data Access logging for Cloud SQL instance is disabled by default, thus we need to enable it (if not enabled).
+
+- Go to "IAM & Admin" -> "Audit Logs"
+- Locate "Cloud SQL"
+- on "Permission Types", check the "Admin read"
+
+You can use following query to filter the events:
+
+` + CodeBlock + `
+resource.type="cloudsql_database"
+protoPayload.serviceName="cloudsql.googleapis.com"
+protoPayload.methodName="cloudsql.instances.export"
+` + CodeBlock + `
+
+Sample event (shortened for readability):
+
+` + CodeBlock + `json
+{
+ "logName": "projects/my-project-id/logs/cloudaudit.googleapis.com%2Factivity",
+ "protoPayload": {
+ "authenticationInfo": {
+ "principalEmail": "username@service.com",
+ },
+ "methodName": "cloudsql.instances.export",
+ "request": {
+ @type: "type.googleapis.com/google.cloud.sql.v1.SqlInstancesExportRequest",
+ "body": {
+ "exportContext": {
+ "databases": [
+ "stratus-db"
+ ],
+ "fileType": "SQL",
+ "uri": "gs://my-bucket-id/dump.sql.gz"
+ }
+ },
+ "instance": "my-cloudsql-instance-id",
+ }
+ "resourceName": "projects/my-project-id/instances/my-cloudsql-instance-id",
+ "serviceName": "cloudsql.googleapis.com",
+ },
+ "resource": {
+ "type": "cloudsql_database"
+ },
+ "severity": "INFO"
+}
+` + CodeBlock + `
+
+subsequently, detect the 'storage.objects.create' event for creating the object on bucket.
+
+` + CodeBlock + `json
+{
+ "logName": "projects/my-project-id/logs/cloudaudit.googleapis.com%2Factivity",
+ "protoPayload": {
+ "authenticationInfo": {
+ "principalEmail": "username@service.com",
+ },
+ "methodName": "storage.objects.create",
+ "resourceName": "projects/_/buckets/my-bucket-id/objects/dump.sql.gz",
+ "serviceName": "cloudsql.googleapis.com",
+ },
+ "resource": {
+ "type": "gcs_bucket"
+ },
+ "severity": "INFO"
+}
+` + CodeBlock + `
+`,
+ Platform: stratus.GCP,
+ IsIdempotent: true,
+ MitreAttackTactics: []mitreattack.Tactic{ mitreattack.Exfiltration },
+ PrerequisitesTerraformCode: tf,
+ Detonate: detonate,
+ })
+}
+
+func detonate(params map[string]string, providers stratus.CloudProviders) error {
+ gcp := providers.GCP()
+ ctx := context.Background()
+
+ projectId := gcp.GetProjectId()
+ bucketName := params["bucket_name"]
+ sqlInstance := params["sql_instance"]
+
+ // create service for API communication
+ service, err := sqladmin.NewService(ctx, gcp.Options())
+ if err != nil {
+ return fmt.Errorf("Failed to create new service: %v", err)
+ }
+
+ // export the database
+ req := &sqladmin.InstancesExportRequest {
+ ExportContext: &sqladmin.ExportContext{
+ Databases: []string{"stratus-db"},
+ FileType: "SQL",
+ Uri: fmt.Sprintf("gs://%s/dump.sql.gz", bucketName),
+ },
+ }
+
+ if op, err := service.Instances.Export(projectId, sqlInstance, req).Do(); err != nil {
+ return fmt.Errorf("Failed to export database: %v", err)
+ }
+
+ // wait for the export operation to complete
+ for {
+ op, err := service.Operations.Get(projectId, op.Name).Do()
+ if err != nil {
+ return fmt.Errorf("Failed to get operation status: %v", err)
+ }
+
+ if op.Status == "DONE" {
+ if op.Error != nil {
+ return fmt.Errorf("Export operation failed: %v", op.Error.Errors)
+ }
+ break
+ }
+
+ log.Println("Exporting in progress... waiting")
+ time.Sleep(10 * time.Second)
+ }
+
+ log.Println("Database has been exported to the bucket")
+
+ return nil
+}
\ No newline at end of file
diff --git a/v2/internal/attacktechniques/gcp/exfiltration/sql-export-bucket/main.tf b/v2/internal/attacktechniques/gcp/exfiltration/sql-export-bucket/main.tf
new file mode 100644
index 000000000..dcc4e6790
--- /dev/null
+++ b/v2/internal/attacktechniques/gcp/exfiltration/sql-export-bucket/main.tf
@@ -0,0 +1,107 @@
+terraform {
+ required_providers {
+ google = {
+ source = "hashicorp/google"
+ version = "~> 6.18.1"
+ }
+ httpclient = {
+ source = "dmachard/http-client"
+ version = "0.0.3"
+ }
+ }
+}
+
+provider "google" {
+ default_labels = {
+ stratus-red-team = "true"
+ }
+}
+
+locals {
+ resource_prefix = "stratus-red-team-sep"
+ region = "us-east1"
+ instance_tier = "db-f1-micro"
+ default_password = "StratusRedTeam"
+}
+
+resource "random_string" "suffix" {
+ special = false
+ length = 16
+ min_lower = 16
+}
+
+data "google_client_config" "current" { }
+
+resource "google_sql_database_instance" "instance" {
+ name = "${local.resource_prefix}-sql-${random_string.suffix.result}"
+
+ database_version = "MYSQL_5_7"
+ region = local.region
+
+ settings {
+ tier = local.instance_tier
+ }
+
+ deletion_protection = false
+}
+
+resource "google_sql_database" "database" {
+ name = "stratus-db"
+
+ instance = google_sql_database_instance.instance.name
+ charset = "utf8"
+ collation = "utf8_general_ci"
+}
+
+resource "google_sql_user" "user" {
+ name = "root"
+ instance = google_sql_database_instance.instance.name
+ host = "%"
+ password = local.default_password
+}
+
+resource "google_storage_bucket" "bucket" {
+ name = "${local.resource_prefix}-bucket-${random_string.suffix.result}"
+
+ location = local.region
+ storage_class = "STANDARD"
+ force_destroy = true
+ uniform_bucket_level_access = true
+}
+
+resource "google_storage_bucket_iam_member" "importer" {
+ bucket = google_storage_bucket.bucket.name
+ role = "roles/storage.objectAdmin"
+ member = "serviceAccount:${google_sql_database_instance.instance.service_account_email_address}"
+}
+
+resource "google_storage_bucket_object" "sql_file" {
+ name = "init.sql"
+ bucket = google_storage_bucket.bucket.id
+ content = base64decode("Q1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgdXNlcnMgKAogICAgYGlkYCBJTlQoMTApIE5PVCBOVUxMIEFVVE9fSU5DUkVNRU5ULAogICAgYHVzZXJuYW1lYCBWQVJDSEFSKDI1NSkgTk9UIE5VTEwsCiAgICBgcGFzc3dvcmRgIFZBUkNIQVIoMjU1KSBOT1QgTlVMTCwKICAgIFBSSU1BUlkgS0VZIGBpZGAgKGBpZGApCik7CklOU0VSVCBJTlRPIGB1c2Vyc2AoYHVzZXJuYW1lYCxgcGFzc3dvcmRgKSBWQUxVRVMoInNhdHJpYUB0aGlzY29tcGFueS5pZCIsTUQ1KCdQQHNzdzByZCcpKTsKSU5TRVJUIElOVE8gYHVzZXJzYChgdXNlcm5hbWVgLGBwYXNzd29yZGApIFZBTFVFUygiYWR5QHRoaXNjb21wYW55LmlkIixNRDUoJ1BAc3N3MHJkJykpOwpJTlNFUlQgSU5UTyBgdXNlcnNgKGB1c2VybmFtZWAsYHBhc3N3b3JkYCkgVkFMVUVTKCJwcmFkYW5hQHRoaXNjb21wYW55LmlkIixNRDUoJ1BAc3N3MHJkJykpOwo=")
+ content_type = "text/plain"
+}
+
+data "httpclient_request" "req" {
+ url = "https://sqladmin.googleapis.com/v1/projects/${data.google_client_config.current.project}/instances/${google_sql_database_instance.instance.name}/import"
+ request_method = "POST"
+ request_headers = {
+ Content-Type: "application/json; charset=utf-8",
+ Authorization: "Bearer ${data.google_client_config.current.access_token}",
+ }
+ request_body = "{'importContext':{'fileType':'SQL','uri':'gs://${google_storage_bucket.bucket.id}/init.sql','database':'stratus-db'}}"
+
+ depends_on = [google_storage_bucket_iam_member.importer]
+}
+
+output "bucket_name" {
+ value = google_storage_bucket.bucket.name
+}
+
+output "sql_instance" {
+ value = google_sql_database_instance.instance.name
+}
+
+output "display" {
+ value = format("Cloud SQL '%s' ready (%s)", google_sql_database_instance.instance.name, data.httpclient_request.req.response_code)
+}
\ No newline at end of file
diff --git a/v2/internal/attacktechniques/main.go b/v2/internal/attacktechniques/main.go
index c66c255c9..68bcfe7bb 100644
--- a/v2/internal/attacktechniques/main.go
+++ b/v2/internal/attacktechniques/main.go
@@ -58,6 +58,7 @@ import (
_ "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"
+ _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/exfiltration/sql-export-bucket"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/persistence/backdoor-service-account-policy"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/persistence/create-admin-service-account"
_ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/persistence/create-service-account-key"