09.LAB-XX · Capstone

Cloud Attack Path Walker

Walk the Capital One pattern step by step. Same attack shape in AWS, Azure, GCP — with the provider-specific defenses that block each hop.

The 2019 Capital One breach is the textbook example of a cloud attack chain: a web application bug let an attacker reach the cloud's instance metadata service, the metadata service returned credentials for the workload's role, the role had permissions to read S3, and the attacker read ~100 million records of customer data.

The mechanics are not AWS-specific. The same chain runs in Azure (via IMDS → managed identity token) and in GCP (via metadata server → service account token). This lab walks all five steps in all three clouds, marks where the chain becomes provider-specific, and shows which defense at which step would have broken it.

01
Web app vulnerability — SSRF

The application has a server-side request forgery bug. It accepts a URL parameter (an image to fetch, a webhook to POST, a remote document to parse) and dutifully makes the HTTP request from the server. The attacker submits a URL pointing inside the cloud's metadata service.

# The attacker's request to the vulnerable app POST /generate-preview HTTP/1.1 { "url": "http://169.254.169.254/latest/meta-data/" } # The app obediently fetches that URL from inside its own VPC GET http://169.254.169.254/latest/meta-data/
Defense at this stepFix the SSRF. Validate URLs against an allow-list of legitimate destinations. Block the cloud metadata IP at the egress layer. This is a generic web-app fix — it's the same control regardless of cloud provider.
02
Reach the metadata service

The metadata IP 169.254.169.254 is the same address in every major cloud (it's the link-local "service discovery" address standardized by IETF). The path after that differs by provider, but the attacker now has the SSRF target dialed in. They iterate through paths to find the credential endpoint.

AWS

http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>
Returns temporary AWS credentials JSON: AccessKeyId, SecretAccessKey, Token.

Azure

http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/
Returns a managed-identity bearer token.

GCP

http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
Returns an OAuth access token for the attached service account.

Defense at this stepRequire the hardened metadata endpoint. AWS: IMDSv2 (session-token-required) blocks SSRF-style fetches because the SSRF can't easily craft the PUT request to get the session token. Azure: requires the Metadata: true header on every request — many SSRF tools can't set custom headers. GCP: requires the Metadata-Flavor: Google header, same defense. Turn these on; they break SSRF→IMDS exfiltration in real life.
03
Use the stolen credentials

The attacker now holds valid, short-lived credentials for the workload's identity. From here, they shift from web-vulnerability exploitation to cloud-API attack — calling cloud APIs as the workload, from wherever they want.

# Configure the stolen creds and run a listing export AWS_ACCESS_KEY_ID=ASIA... export AWS_SECRET_ACCESS_KEY=... export AWS_SESSION_TOKEN=... aws s3 ls # Whatever buckets the workload's role could list, the attacker can now list.
Defense at this stepLeast-privilege roles. If the workload's role only had s3:GetObject on its own bucket, the stolen credentials can read that bucket and nothing else. Capital One's role had ListAllMyBuckets + GetObject on more S3 than the workload needed — that is what made the blast radius catastrophic.
04
Walk the blast radius

The attacker now has cloud credentials and an API endpoint. They explore: what else can these credentials do? Calls like iam:ListAttachedRolePolicies, sts:GetCallerIdentity, and iam:SimulatePrincipalPolicy reveal the permission boundary.

If the role can assume another role (cross-account, cross-OU), they assume it. If it can read secrets, they read them. If it can write logs, they tamper with the trail. The blast radius is what they walk — not what they had to start with.

Defense at this stepTwo things: aws:SourceVpce / Azure Storage firewall / GCP VPC-SC — even valid credentials fail when used from outside the perimeter. And continuous monitoring — GuardDuty, Defender, Chronicle — surfaces "this role is being used from a country we don't operate in" within minutes. Detection here is the difference between a contained near-miss and a public breach.
05
Exfiltrate — the actual damage

The attacker pulls the data out. In Capital One's case, ~100 million records from S3. The actual download from cloud storage to attacker-controlled infrastructure is the loudest possible operation, but only loud to someone watching.

# A single aws s3 sync command can pull terabytes aws s3 sync s3://capital-one-data-bucket ./exfil/ # Volume of bytes leaving the bucket is enormous.
Defense at this stepData perimeter — AWS bucket policies with aws:SourceVpce conditions, Azure storage account public access disabled, GCP VPC Service Controls — force the data to stay inside the perimeter even if credentials leak. Anomaly detection — sudden 100× spike in egress bytes from a bucket should fire an alert. Customer-managed KMS keys with rate-limited access make slow exfiltration possible but high-velocity dumps detectable.

Where each defense cut the chain

Every step has a defense that would have broken the attack. Combine multiple defenses and you get defense in depth — a single failure doesn't lead to a breach.

  1. Fix the SSRF — the application bug. URL allow-listing; egress blocking. Stops the attack at step 1.
  2. Harden the metadata endpoint — IMDSv2 / Metadata-Flavor header. Stops at step 2 even if SSRF is present.
  3. Least-privilege role — the workload's identity has only the permissions it needs. Limits damage at step 3.
  4. Data perimeter — SourceVpce / Storage firewall / VPC-SC. Stops step 4–5 even with stolen credentials.
  5. Anomaly detection — GuardDuty / Defender / Chronicle. Surfaces step 4–5 in time to respond.
The point

Cloud attack paths are multi-step chains where each step has a known defense. The provider-specific names differ; the architecture of the chain doesn't. You can read a Capital-One-shaped post-mortem in AWS terms, then translate the same chain to Azure or GCP, and the defenses map cleanly.

This is the value of multi-cloud security thinking: a defender who understands the chain in the abstract can apply the right controls in any cloud. A defender who only understands "AWS has IMDSv2" misses the Azure or GCP variants when they meet them. Build the model first; learn the vocabulary second.

References

Formatted in APA 7. Alphabetized by first author's last name.

  1. Amazon Web Services. (n.d.). Configure the Instance Metadata Service (IMDSv2). AWS EC2 User Guide. https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html
  2. Google Cloud. (n.d.). Storing and retrieving instance metadata. Compute Engine documentation. https://cloud.google.com/compute/docs/metadata/overview
  3. Microsoft. (n.d.). Azure Instance Metadata Service for Linux. Microsoft Learn. https://learn.microsoft.com/en-us/azure/virtual-machines/linux/instance-metadata-service
  4. U.S. Department of Justice. (2019, July 29). Seattle tech worker arrested for data theft involving large financial services company [Press release]. https://www.justice.gov/usao-wdwa/pr/seattle-tech-worker-arrested-data-theft-involving-large-financial-services-company