Chapter 10 — Hands-on: attack and defend a cloud account
Brief
Run a complete offense-then-defense cycle against a deliberately-vulnerable AWS environment in your sandbox: walk an attack path from a low-privileged credential to customer data, then close every edge and prove the path is dead, then add detection for the residual risk. This is the MODEL -> ATTACK -> DETECT -> DEFEND loop from Chapter 0.2 at full size.
Setup
* Sandbox AWS account (its own; budget alarm at $5, stop at $20).
* Deploy CloudGoat's `iam_privesc_by_rollback` and
`ec2_ssrf` scenarios, OR BishopFox `IAM Vulnerable`, OR build the
SecureShop-mini stack from this guide's repo (a VPC, an EC2 "web"
host with an image-proxy SSRF, an over-broad instance role, an
`ss-exports` bucket with a fake PII file, IMDSv1 enabled).
* Tools: awscli, pacu, CloudFox, PMapper, cloudsplaining, Prowler,
ScoutSuite, Stratus Red Team.
Part 1 — Model (30 min)
1. From the starting creds, run CloudFox (`cloudfox aws all-checks`)
and enumerate-iam. Build the node/edge list (Ch 1).
2. Run PMapper: `pmapper graph create`, then
`pmapper argquery --preset privesc` and
`pmapper query "who can do s3:GetObject with arn:aws:s3:::ss-exports/*"`.
3. Draw the attack-path graph from `[external:anon]` and from
`[creds:starting-role]` to `[data:ss-exports]`. Mark the chokepoint.
Part 2 — Attack (60 min)
Walk at least one full path end to end, documenting each command and
its output:
[ ] SSRF path: hit the image-proxy with
url=http://169.254.169.254/latest/meta-data/iam/security-credentials/
-> get role creds (IMDSv1) -> configure them -> `aws s3 ls
s3://ss-exports` -> download the fake PII file.
[ ] IAM privesc path: use a privesc primitive (Ch 6) to reach admin,
then read the bucket "legitimately".
[ ] Note for each step: what permission/misconfig enabled it, and how
noisy it is (would anything log/alert today?).
Part 3 — Defend (60 min)
Close every edge, cheapest chokepoint first, re-testing after each:
[ ] Enforce IMDSv2 hop-limit-1 on the instance (and add the SCP so new
instances can't regress). Re-run SSRF -> creds no longer reachable.
[ ] Allowlist the image-proxy's destination host + block link-local /
RFC1918 / metadata IPs after DNS resolution (G1 Ch 44 + Ch 33 here).
Re-test.
[ ] Scope the instance role: `s3:GetObject` on
`arn:aws:s3:::ss-public-assets/*` only; move exports to a bucket
only `exports-worker-role` can read; add `aws:sourceVpce` condition.
[ ] Kill the privesc primitive (scope `iam:PassRole`, add a permission
boundary, add SCP denies).
[ ] Turn on S3 Block Public Access (account-wide), SSE-KMS with a
customer CMK, and default EBS encryption.
[ ] Re-run PMapper and CloudFox -> confirm no path from anon or from
the starting creds reaches `ss-exports`.
Part 4 — Detect (30 min)
For the residual risk (someone with valid `exports-worker-role` creds
misusing them), add detection:
[ ] GuardDuty enabled; generate sample findings; confirm
`UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration` and
`Exfiltration:S3/AnomalousBehavior` reach the security account.
[ ] A CloudTrail metric filter / EventBridge rule: `exports-worker-role`
session used from a `sourceIPAddress` outside your VPC/NAT ranges,
OR a `GetObject` volume spike on `ss-exports`. Alarm -> SNS.
[ ] Re-run the (now-broken) attack with valid creds from an external
IP; confirm the alert fires and note latency.
Deliverable
~/sec-lab/adv/reports/p2-cloud.md: the attack-path graph (before/after), every
attack command with output, every fix with the re-test that proves the edge is
cut, and the detection rules with their fire evidence and latency. Plus a
one-paragraph "what was the chokepoint and why".
Definition of done
- At least one full attack path walked and documented from creds/anon to data.
- Every edge on that path closed, each with a passing re-test.
- PMapper/CloudFox show no remaining path to the sensitive bucket.
- IMDSv2, Block Public Access, SSE-KMS, scoped
PassRole, and a permission boundary all in place (as Terraform, ideally). - GuardDuty + at least one custom near-real-time detection, both proven to fire.
- Everything torn down; budget checked.
Rubric (/100)
Attack-path model (nodes/edges/chokepoint) ..... 15
Attack executed and clearly documented ......... 20
Every edge closed with a proving re-test ....... 30
Guardrails as code (SCP + Terraform) .......... 15
Detection built and proven (fidelity+latency) .. 15
Report quality ................................ 5
Further reading
- Practice: CloudGoat (Rhino),
flaws.cloud/flaws2.cloud, BishopFoxIAM Vulnerable,pwnedlabs.io, AWS "CIRT" workshops. - Tools: Pacu (AWS exploitation framework) docs; CloudFox (BishopFox); PMapper; Stratus Red Team; Prowler + ScoutSuite for the defensive sweep.
- Reading: "Lesser Known Techniques for Attacking AWS" (Rhino); the Capital
One breach technical post-mortems (re-read now with the full IAM picture);
hackingthe.cloud. - Defense: AWS "Incident Response" whitepaper; the "AWS Customer Playbook Framework" repo.
End of Part 2 — Milestone check
- I can draw the shared-responsibility line for IaaS/PaaS/FaaS and name the pieces of the identity plane
- I can recite AWS policy evaluation order and what an explicit Deny does
- I have escalated from low-priv to admin in a lab two ways, then broken both paths and confirmed with PMapper
- I can design a multi-account structure and a denylist SCP set, and say why the management account runs nothing
- I can build a default-deny VPC with private endpoints and FQDN egress control, and explain why egress control is the exfil control
- I can implement envelope encryption with a per-tenant key hierarchy and explain crypto-shredding
- I completed the attack-and-defend cloud lab end to end with proven detection