From d49ce6c878027d6702f04bcaf704377fb54268f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Mar=C3=A9chal?= Date: Thu, 26 Mar 2026 15:36:42 +0100 Subject: [PATCH 1/3] New attack technique: Invoke Vertex AI Model (gcp.impact.invoke-vertex-ai-model) Co-Authored-By: Claude Sonnet 4.6 --- .../GCP/gcp.impact.invoke-vertex-ai-model.md | 55 +++++++++ docs/attack-techniques/GCP/index.md | 2 + docs/attack-techniques/list.md | 1 + docs/index.yaml | 7 ++ v2/go.mod | 5 + v2/go.sum | 6 + .../gcp/impact/invoke-vertex-ai-model/main.go | 106 ++++++++++++++++++ v2/internal/attacktechniques/main.go | 1 + 8 files changed, 183 insertions(+) create mode 100755 docs/attack-techniques/GCP/gcp.impact.invoke-vertex-ai-model.md create mode 100644 v2/internal/attacktechniques/gcp/impact/invoke-vertex-ai-model/main.go diff --git a/docs/attack-techniques/GCP/gcp.impact.invoke-vertex-ai-model.md b/docs/attack-techniques/GCP/gcp.impact.invoke-vertex-ai-model.md new file mode 100755 index 000000000..686c76056 --- /dev/null +++ b/docs/attack-techniques/GCP/gcp.impact.invoke-vertex-ai-model.md @@ -0,0 +1,55 @@ +--- +title: Invoke a Vertex AI Model +--- + +# Invoke a Vertex AI Model + + + idempotent + +Platform: GCP + +## Mappings + +- MITRE ATT&CK + - Impact + + + +## Description + + +Invokes a Gemini generative AI model via the Vertex AI API. This simulates +an attacker who has obtained access to a GCP service account and abuses it +to run large language model workloads, incurring unexpected costs for the +victim organization. + +Prerequisites: + +- AI Platform API enabled (gcloud services enable aiplatform.googleapis.com) + +Detonation: + +- Call the Vertex AI API to generate content using a Gemini model + in the us-central1 region + +References: + +- https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference +- https://cloud.google.com/vertex-ai/docs/reference/rest/v1/projects.locations.endpoints/generateContent + + +## Instructions + +```bash title="Detonate with Stratus Red Team" +stratus detonate gcp.impact.invoke-vertex-ai-model +``` +## Detection + + +Identify unexpected Vertex AI model invocations by monitoring for +google.cloud.aiplatform.v1.PredictionService.GenerateContent events in +GCP Data Access audit logs, particularly from unexpected service accounts or at +unusual times/volumes. + + diff --git a/docs/attack-techniques/GCP/index.md b/docs/attack-techniques/GCP/index.md index 049274801..18d1840c9 100755 --- a/docs/attack-techniques/GCP/index.md +++ b/docs/attack-techniques/GCP/index.md @@ -99,3 +99,5 @@ Note that some Stratus attack techniques may correspond to more than a single AT - [Create GCE Instances in Multiple Zones](./gcp.impact.create-instances-in-multiple-zones.md) + - [Invoke a Vertex AI Model](./gcp.impact.invoke-vertex-ai-model.md) + diff --git a/docs/attack-techniques/list.md b/docs/attack-techniques/list.md index 31780c8d5..6f85e31a7 100755 --- a/docs/attack-techniques/list.md +++ b/docs/attack-techniques/list.md @@ -86,6 +86,7 @@ This page contains the list of all Stratus Attack Techniques. | [Exfiltrate Compute Disk by sharing a snapshot](./GCP/gcp.exfiltration.share-compute-snapshot.md) | [GCP](./GCP/index.md) | Exfiltration | | [Create a GCE GPU Virtual Machine](./GCP/gcp.impact.create-gpu-vm.md) | [GCP](./GCP/index.md) | Impact | | [Create GCE Instances in Multiple Zones](./GCP/gcp.impact.create-instances-in-multiple-zones.md) | [GCP](./GCP/index.md) | Impact | +| [Invoke a Vertex AI Model](./GCP/gcp.impact.invoke-vertex-ai-model.md) | [GCP](./GCP/index.md) | Impact | | [Steal and Use the GCE Default Service Account Token from Outside Google Cloud](./GCP/gcp.initial-access.use-compute-sa-outside-gcp.md) | [GCP](./GCP/index.md) | Credential Access, Initial Access | | [Register SSH public key to instance metadata](./GCP/gcp.lateral-movement.add-sshkey-instance-metadata.md) | [GCP](./GCP/index.md) | Lateral Movement, Persistence | | [Backdoor a GCP Service Account through its IAM Policy](./GCP/gcp.persistence.backdoor-service-account-policy.md) | [GCP](./GCP/index.md) | Persistence | diff --git a/docs/index.yaml b/docs/index.yaml index cb08a49c3..f4f5b5c16 100644 --- a/docs/index.yaml +++ b/docs/index.yaml @@ -692,6 +692,13 @@ GCP: - Impact platform: GCP isIdempotent: false + - id: gcp.impact.invoke-vertex-ai-model + name: Invoke a Vertex AI Model + isSlow: false + mitreAttackTactics: + - Impact + platform: GCP + isIdempotent: true 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 diff --git a/v2/go.mod b/v2/go.mod index c74ad2779..2e5c59b36 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -7,8 +7,10 @@ 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/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 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.5.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.1.0 @@ -59,10 +61,13 @@ require ( ) require ( + cloud.google.com/go v0.118.0 // indirect + cloud.google.com/go/aiplatform v1.70.0 // indirect cloud.google.com/go/auth v0.14.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect cloud.google.com/go/compute/metadata v0.6.0 // indirect cloud.google.com/go/iam v1.3.1 // indirect + cloud.google.com/go/longrunning v0.6.4 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 v2.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.3.0 // indirect diff --git a/v2/go.sum b/v2/go.sum index 3f0f59eb3..7a01c7356 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -1,6 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.118.0 h1:tvZe1mgqRxpiVa3XlIGMiPcEUbP1gNXELgD4y/IXmeQ= cloud.google.com/go v0.118.0/go.mod h1:zIt2pkedt/mo+DQjcT4/L3NDxzHPR29j5HcclNH+9PM= +cloud.google.com/go/aiplatform v1.70.0 h1:vnqsPkgcwlDEpWl9t6C3/HLfHeweuGXs2gcYTzH6dMs= +cloud.google.com/go/aiplatform v1.70.0/go.mod h1:1cewyC4h+yvRs0qVvlCuU3V6j1pJ41doIcroYX3uv8o= cloud.google.com/go/auth v0.14.0 h1:A5C4dKV/Spdvxcl0ggWwWEzzP7AZMJSEIgrkngwhGYM= cloud.google.com/go/auth v0.14.0/go.mod h1:CYsoRL1PdiDuqeQpZE0bP2pnPrGqFcOkI0nldEQis+A= cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M= @@ -11,8 +13,12 @@ cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4 cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= cloud.google.com/go/iam v1.3.1 h1:KFf8SaT71yYq+sQtRISn90Gyhyf4X8RGgeAVC8XGf3E= cloud.google.com/go/iam v1.3.1/go.mod h1:3wMtuyT4NcbnYNPLMBzYRFiEfjKfJlLVLrisE7bwm34= +cloud.google.com/go/longrunning v0.6.4 h1:3tyw9rO3E2XVXzSApn1gyEEnH2K9SynNQjMlBi3uHLg= +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/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= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 h1:JXg2dwJUmPB9JmtVmdEB16APJ7jurfbY5jnfXpJoRMc= diff --git a/v2/internal/attacktechniques/gcp/impact/invoke-vertex-ai-model/main.go b/v2/internal/attacktechniques/gcp/impact/invoke-vertex-ai-model/main.go new file mode 100644 index 000000000..9d41f892e --- /dev/null +++ b/v2/internal/attacktechniques/gcp/impact/invoke-vertex-ai-model/main.go @@ -0,0 +1,106 @@ +package gcp + +import ( + "context" + "fmt" + "log" + "strings" + + "cloud.google.com/go/vertexai/genai" + "github.com/datadog/stratus-red-team/v2/pkg/stratus" + "github.com/datadog/stratus-red-team/v2/pkg/stratus/mitreattack" +) + +// candidateModels is tried in order until one succeeds. Uses stable aliases +// (no version suffix) so GCP automatically resolves them to the current supported +// version — aliases don't have retirement dates, unlike pinned version IDs. +// Ordered cheapest first. +var candidateModels = []string{ + "gemini-2.5-flash-lite", + "gemini-2.5-flash", + "gemini-2.5-pro", +} + +func init() { + stratus.GetRegistry().RegisterAttackTechnique(&stratus.AttackTechnique{ + ID: "gcp.impact.invoke-vertex-ai-model", + FriendlyName: "Invoke a Vertex AI Model", + Description: ` +Invokes a Gemini generative AI model via the Vertex AI API. This simulates +an attacker who has obtained access to a GCP service account and abuses it +to run large language model workloads, incurring unexpected costs for the +victim organization. + +Prerequisites: + +- AI Platform API enabled (gcloud services enable aiplatform.googleapis.com) + +Detonation: + +- Call the Vertex AI API to generate content using a Gemini model + in the us-central1 region + +References: + +- https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference +- https://cloud.google.com/vertex-ai/docs/reference/rest/v1/projects.locations.endpoints/generateContent +`, + Detection: ` +Identify unexpected Vertex AI model invocations by monitoring for +google.cloud.aiplatform.v1.PredictionService.GenerateContent events in +GCP Data Access audit logs, particularly from unexpected service accounts or at +unusual times/volumes. +`, + Platform: stratus.GCP, + IsIdempotent: true, + MitreAttackTactics: []mitreattack.Tactic{mitreattack.Impact}, + Detonate: detonate, + }) +} + +func detonate(_ map[string]string, providers stratus.CloudProviders) error { + gcp := providers.GCP() + projectId := gcp.GetProjectId() + ctx := context.Background() + + client, err := genai.NewClient(ctx, projectId, "us-central1", gcp.Options()) + if err != nil { + return fmt.Errorf("failed to create Vertex AI client: %w", err) + } + defer client.Close() + + for _, modelName := range candidateModels { + log.Printf("Invoking Vertex AI model %s in project %s\n", modelName, projectId) + resp, err := client.GenerativeModel(modelName).GenerateContent( + ctx, + genai.Text("Tell me a joke about cloud security."), + ) + if err != nil { + if isNotFound(err) { + log.Printf("Model %s not available in this project, trying next\n", modelName) + continue + } + return fmt.Errorf("failed to invoke Vertex AI model: %w", err) + } + + if len(resp.Candidates) == 0 || len(resp.Candidates[0].Content.Parts) == 0 { + return fmt.Errorf("received empty response from Vertex AI model %s", modelName) + } + + log.Printf("Successfully invoked Vertex AI model %s. Response: %v\n", + modelName, resp.Candidates[0].Content.Parts[0]) + return nil + } + + return fmt.Errorf("no Vertex AI model available in project %s (tried: %s) — ensure the Vertex AI API is enabled", + projectId, strings.Join(candidateModels, ", ")) +} + +// isNotFound returns true when the gRPC error indicates the model does not exist +// or is not accessible in this project. +func isNotFound(err error) bool { + msg := err.Error() + return strings.Contains(msg, "NOT_FOUND") || + strings.Contains(msg, "code = NotFound") || + strings.Contains(msg, "was not found") +} diff --git a/v2/internal/attacktechniques/main.go b/v2/internal/attacktechniques/main.go index 48c792fb1..2729e25b3 100644 --- a/v2/internal/attacktechniques/main.go +++ b/v2/internal/attacktechniques/main.go @@ -83,6 +83,7 @@ import ( _ "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/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/initial-access/use-compute-sa-outside-gcp" _ "github.com/datadog/stratus-red-team/v2/internal/attacktechniques/gcp/lateral-movement/add-sshkey-instance-metadata" From 3f299d5e950c80f445277229a7c6c333b8168319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Mar=C3=A9chal?= Date: Mon, 30 Mar 2026 14:42:57 +0200 Subject: [PATCH 2/3] Add external references for technique documentation Co-Authored-By: Claude Opus 4.6 (1M context) --- .../attacktechniques/gcp/impact/invoke-vertex-ai-model/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/v2/internal/attacktechniques/gcp/impact/invoke-vertex-ai-model/main.go b/v2/internal/attacktechniques/gcp/impact/invoke-vertex-ai-model/main.go index 9d41f892e..57f0f156c 100644 --- a/v2/internal/attacktechniques/gcp/impact/invoke-vertex-ai-model/main.go +++ b/v2/internal/attacktechniques/gcp/impact/invoke-vertex-ai-model/main.go @@ -44,6 +44,8 @@ References: - https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference - https://cloud.google.com/vertex-ai/docs/reference/rest/v1/projects.locations.endpoints/generateContent +- https://sysdig.com/blog/llmjacking-stolen-cloud-credentials-used-in-new-ai-attack/ +- https://unit42.paloaltonetworks.com/privilege-escalation-llm-model-exfil-vertex-ai/ `, Detection: ` Identify unexpected Vertex AI model invocations by monitoring for From 4c60a98009e89c6dfe9c5409b977492fc09c1c56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Mar=C3=A9chal?= Date: Wed, 1 Apr 2026 10:48:18 +0200 Subject: [PATCH 3/3] Remove HackTricks refs, regenerate docs Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/attack-techniques/GCP/gcp.impact.invoke-vertex-ai-model.md | 2 ++ docs/attack-techniques/mitre-attack-coverage-matrices.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/attack-techniques/GCP/gcp.impact.invoke-vertex-ai-model.md b/docs/attack-techniques/GCP/gcp.impact.invoke-vertex-ai-model.md index 686c76056..088676c38 100755 --- a/docs/attack-techniques/GCP/gcp.impact.invoke-vertex-ai-model.md +++ b/docs/attack-techniques/GCP/gcp.impact.invoke-vertex-ai-model.md @@ -37,6 +37,8 @@ References: - https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference - https://cloud.google.com/vertex-ai/docs/reference/rest/v1/projects.locations.endpoints/generateContent +- https://sysdig.com/blog/llmjacking-stolen-cloud-credentials-used-in-new-ai-attack/ +- https://unit42.paloaltonetworks.com/privilege-escalation-llm-model-exfil-vertex-ai/ ## Instructions diff --git a/docs/attack-techniques/mitre-attack-coverage-matrices.md b/docs/attack-techniques/mitre-attack-coverage-matrices.md index f63941556..90649bfc3 100644 --- a/docs/attack-techniques/mitre-attack-coverage-matrices.md +++ b/docs/attack-techniques/mitre-attack-coverage-matrices.md @@ -57,7 +57,7 @@ This provides coverage matrices of MITRE ATT&CK tactics and techniques currently 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 +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 itInvoke a Vertex AI Model 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