Cloud Security Lab Setup
Build vulnerable cloud environments for practicing AWS, Azure, and GCP penetration testing. Learn cloud misconfigurations in a safe, controlled setting.
Cost Warning
Vulnerable Cloud Labs
CloudGoat (AWS)
Rhino Security's "Vulnerable by Design" AWS deployment. Multiple attack scenarios.
- ✓ IAM privilege escalation
- ✓ EC2 SSRF to metadata
- ✓ Lambda exploitation
- ✓ S3 misconfiguration
AzureGoat
Vulnerable Azure environment with common misconfigurations.
- ✓ Storage account exposure
- ✓ App Service vulnerabilities
- ✓ Managed Identity abuse
- ✓ Key Vault misconfig
GCPGoat
Intentionally vulnerable Google Cloud Platform deployment.
- ✓ Compute Engine misconfig
- ✓ Cloud Storage exposure
- ✓ IAM escalation
- ✓ Metadata service abuse
Kubernetes Goat
Interactive Kubernetes security learning platform with 20+ scenarios.
- ✓ Container escape
- ✓ RBAC misconfig
- ✓ Secret exposure
- ✓ Network policies
CloudGoat Setup (AWS)
Prerequisites
# Install required tools
pip3 install awscli boto3
curl "https://releases.hashicorp.com/terraform/1.5.0/terraform_1.5.0_linux_amd64.zip" -o terraform.zip
unzip terraform.zip && sudo mv terraform /usr/local/bin/
# Configure AWS credentials
aws configure
# Enter: AWS Access Key, Secret Key, Region (us-east-1), Output (json)# Install required tools
pip3 install awscli boto3
curl "https://releases.hashicorp.com/terraform/1.5.0/terraform_1.5.0_linux_amd64.zip" -o terraform.zip
unzip terraform.zip && sudo mv terraform /usr/local/bin/
# Configure AWS credentials
aws configure
# Enter: AWS Access Key, Secret Key, Region (us-east-1), Output (json)Deploy CloudGoat
# Clone and setup
git clone https://github.com/RhinoSecurityLabs/cloudgoat.git
cd cloudgoat
pip3 install -r requirements.txt
chmod +x cloudgoat.py
# Configure
./cloudgoat.py config profile
./cloudgoat.py config whitelist --auto
# Deploy a scenario
./cloudgoat.py create iam_privesc_by_rollback
# List available scenarios
./cloudgoat.py list all# Clone and setup
git clone https://github.com/RhinoSecurityLabs/cloudgoat.git
cd cloudgoat
pip3 install -r requirements.txt
chmod +x cloudgoat.py
# Configure
./cloudgoat.py config profile
./cloudgoat.py config whitelist --auto
# Deploy a scenario
./cloudgoat.py create iam_privesc_by_rollback
# List available scenarios
./cloudgoat.py list all⚠️ Destroy When Done
# Always destroy resources to avoid charges!
./cloudgoat.py destroy iam_privesc_by_rollback
# Or destroy all scenarios
./cloudgoat.py destroy all# Always destroy resources to avoid charges!
./cloudgoat.py destroy iam_privesc_by_rollback
# Or destroy all scenarios
./cloudgoat.py destroy allLocal Kubernetes Lab
Free Local Option
Kubernetes Goat with Minikube
# Install Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# Start cluster
minikube start --driver=docker --memory=4096
# Install Kubernetes Goat
git clone https://github.com/madhuakula/kubernetes-goat.git
cd kubernetes-goat
chmod +x setup-kubernetes-goat.sh
./setup-kubernetes-goat.sh
# Access the dashboard
minikube service kubernetes-goat-home# Install Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# Start cluster
minikube start --driver=docker --memory=4096
# Install Kubernetes Goat
git clone https://github.com/madhuakula/kubernetes-goat.git
cd kubernetes-goat
chmod +x setup-kubernetes-goat.sh
./setup-kubernetes-goat.sh
# Access the dashboard
minikube service kubernetes-goat-homeTerraform Vulnerable Configs
Deploy specific vulnerable configurations for targeted practice:
S3 Public Bucket
# main.tf - Vulnerable S3
resource "aws_s3_bucket" "vuln" {
bucket = "vuln-bucket-${random_id.id.hex}"
}
resource "aws_s3_bucket_public_access_block" "vuln" {
bucket = aws_s3_bucket.vuln.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}# main.tf - Vulnerable S3
resource "aws_s3_bucket" "vuln" {
bucket = "vuln-bucket-${random_id.id.hex}"
}
resource "aws_s3_bucket_public_access_block" "vuln" {
bucket = aws_s3_bucket.vuln.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}EC2 with IMDS v1
# main.tf - SSRF-vulnerable EC2
resource "aws_instance" "vuln" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t3.micro"
# Vulnerable: IMDSv1 enabled
metadata_options {
http_tokens = "optional"
}
}# main.tf - SSRF-vulnerable EC2
resource "aws_instance" "vuln" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t3.micro"
# Vulnerable: IMDSv1 enabled
metadata_options {
http_tokens = "optional"
}
}SadCloud (NCC Group)
Terraform-based tool that deploys intentionally vulnerable AWS infrastructure covering 22+ services.
# Clone SadCloud
git clone https://github.com/nccgroup/sadcloud.git
cd sadcloud
# Install dependencies
pip install -r requirements.txt
# Deploy specific modules (e.g., vulnerable S3 and IAM)
terraform init
terraform plan -var="s3_public=true" -var="iam_excessive=true"
terraform apply -auto-approve
# ALWAYS destroy when done
terraform destroy -auto-approve# Clone SadCloud
git clone https://github.com/nccgroup/sadcloud.git
cd sadcloud
# Install dependencies
pip install -r requirements.txt
# Deploy specific modules (e.g., vulnerable S3 and IAM)
terraform init
terraform plan -var="s3_public=true" -var="iam_excessive=true"
terraform apply -auto-approve
# ALWAYS destroy when done
terraform destroy -auto-approveSadCloud Covers:
Detection & Monitoring (Purple Team)
Enable cloud-native detection services to see what your attacks look like from a defender's perspective. This turns your cloud lab into a purple team exercise.
AWS Detection Stack
- • CloudTrail — Enable in all regions, log to S3
- • GuardDuty — Threat detection (free 30-day trial)
- • Security Hub — Centralized security findings
- • AWS Config — Track configuration changes
# Enable CloudTrail (CLI)
aws cloudtrail create-trail \
--name lab-trail \
--s3-bucket-name lab-cloudtrail-logs \
--is-multi-region-trail
aws cloudtrail start-logging --name lab-trail
# Enable GuardDuty
aws guardduty create-detector --enable
# After attacking, check findings:
aws guardduty list-findings --detector-id <ID>
aws cloudtrail lookup-events --lookup-attributes \
AttributeKey=EventName,AttributeValue=GetSecretValue# Enable CloudTrail (CLI)
aws cloudtrail create-trail \
--name lab-trail \
--s3-bucket-name lab-cloudtrail-logs \
--is-multi-region-trail
aws cloudtrail start-logging --name lab-trail
# Enable GuardDuty
aws guardduty create-detector --enable
# After attacking, check findings:
aws guardduty list-findings --detector-id <ID>
aws cloudtrail lookup-events --lookup-attributes \
AttributeKey=EventName,AttributeValue=GetSecretValueAzure Detection Stack
- • Microsoft Sentinel — Cloud SIEM (free tier available)
- • Entra ID Logs — Sign-in and audit logs
- • Defender for Cloud — Security posture management
- • Activity Log — Management plane operations
# Enable Azure Activity Log diagnostic setting
az monitor diagnostic-settings create \
--name lab-diag \
--resource /subscriptions/<sub-id> \
--logs '[{"category":"Administrative","enabled":true}]' \
--workspace <log-analytics-id>
# After attacking, query Sentinel:
# SecurityEvent | where EventID == 4625
# AzureActivity | where OperationNameValue contains "vault"
# SigninLogs | where ResultType != 0# Enable Azure Activity Log diagnostic setting
az monitor diagnostic-settings create \
--name lab-diag \
--resource /subscriptions/<sub-id> \
--logs '[{"category":"Administrative","enabled":true}]' \
--workspace <log-analytics-id>
# After attacking, query Sentinel:
# SecurityEvent | where EventID == 4625
# AzureActivity | where OperationNameValue contains "vault"
# SigninLogs | where ResultType != 0Purple Team Workflow
Cost Management Tips
Automated Teardown Script
Destroy-All Script
#!/bin/bash
# destroy-lab.sh - Run after every practice session
echo "[*] Destroying CloudGoat scenarios..."
cd ~/cloudgoat && ./cloudgoat.py destroy all 2>/dev/null
echo "[*] Destroying Terraform resources..."
for dir in ~/labs/terraform/*/; do
cd "$dir" && terraform destroy -auto-approve 2>/dev/null
done
echo "[*] Checking for running EC2 instances..."
aws ec2 describe-instances --filters Name=instance-state-name,Values=running \
--query 'Reservations[].Instances[].InstanceId' --output text
echo "[*] Check your billing dashboard: https://console.aws.amazon.com/billing/"
echo "[!] Done. Verify no resources remain in the AWS console." #!/bin/bash
# destroy-lab.sh - Run after every practice session
echo "[*] Destroying CloudGoat scenarios..."
cd ~/cloudgoat && ./cloudgoat.py destroy all 2>/dev/null
echo "[*] Destroying Terraform resources..."
for dir in ~/labs/terraform/*/; do
cd "$dir" && terraform destroy -auto-approve 2>/dev/null
done
echo "[*] Checking for running EC2 instances..."
aws ec2 describe-instances --filters Name=instance-state-name,Values=running \
--query 'Reservations[].Instances[].InstanceId' --output text
echo "[*] Check your billing dashboard: https://console.aws.amazon.com/billing/"
echo "[!] Done. Verify no resources remain in the AWS console." 💰 Set Billing Alerts
Configure alerts at $5, $10, $25 to catch runaway costs early.
⏰ Use Free Tier
AWS/Azure/GCP offer free tiers. Stay within limits.
🗑️ Destroy Resources
Always terraform destroy after practice sessions.
Troubleshooting FAQ
CloudGoat deploy fails with permission errors
- Ensure your AWS credentials have admin permissions (or at minimum: IAM, EC2, S3, Lambda, RDS)
- Check AWS region is set:
aws configure get region - Some scenarios need specific regions — check the scenario README
- Run
aws sts get-caller-identityto verify credentials are working
Terraform state lock or "resource already exists"
- Force unlock:
terraform force-unlock LOCK_ID - Import existing resource:
terraform import aws_instance.example i-1234567890 - Nuclear option: delete
terraform.tfstateand manually clean up in AWS console - Always run
terraform destroybefore re-deploying
Unexpected cloud charges appeared
- Run the destroy-all script immediately (see Cost Management section)
- Check all regions — resources may have been created in non-default regions
- Review AWS Cost Explorer or Azure Cost Analysis for breakdown
- Set up billing alerts before deploying any lab resources
- Contact cloud provider support — they sometimes waive accidental charges for lab/learning use