Browse CTFs New CTF Sign in

AWS CloudFormation Credential Exposure: Extracting Secrets from Stack Templates

osint_collection Difficulty 1–5 30 min certifiable

Theory

Why This Matters

In 2020, multiple organizations discovered that their CloudFormation stack templates — stored in S3 and accessible via the CloudFormation API — contained plaintext database passwords, API keys, and IAM user credentials that had been hardcoded during initial infrastructure deployments years earlier. Security researchers scanning exposed S3 buckets routinely find .template and .json CloudFormation files with credentials in UserData bootstrap scripts or Parameters default values. Because CloudFormation stores the full rendered template (including parameter values) in the stack's event history and in S3, a single overly-permissive IAM policy or public bucket exposes every secret ever passed to that stack — including secrets that have since been rotated in the application but remain visible in the deployment artifact.

Core Concept

AWS CloudFormation is the Infrastructure-as-Code service that provisions AWS resources from declarative JSON or YAML templates. Templates have several sections where secrets commonly appear: Parameters (the Default field stores the value in plaintext), Metadata (arbitrary key-value pairs often used to pass configuration), and UserData (base64-encoded bootstrap scripts that frequently contain export DB_PASSWORD=... or aws configure set commands).

CloudFormation stores templates in two durable locations: an S3 bucket specified at deploy time (or an auto-created bucket prefixed cf-templates-), and the stack's internal storage accessible via GetTemplate. Stack Events and Outputs can also expose secret values — a template that outputs a generated password or an IAM access key created by the stack will show those values in the Outputs section indefinitely.

NoEcho is the CloudFormation parameter attribute that masks a parameter value in the console and API — it is not encryption, it is masking. The value is still stored in plaintext; it is simply not returned in describe-parameters calls. An attacker with cloudformation:GetTemplate bypasses NoEcho entirely by reading the raw template.

The correct remediation pattern is to store secrets in AWS Secrets Manager or AWS Systems Manager Parameter Store (SecureString), then reference them in the template as dynamic references ({{resolve:secretsmanager:MySecret:SecretString:password}}) — the secret value is never written into the template document.

Technical Deep-Dive

# List all CloudFormation stacks in the current region
aws cloudformation list-stacks 
  --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE 
  --query 'StackSummaries[*].{Name:StackName,Status:StackStatus,Created:CreationTime}' 
  --output table

# Retrieve the full template for a stack (bypasses NoEcho — full parameter values visible)
aws cloudformation get-template --stack-name TargetStack 
  --query 'TemplateBody' --output text > stack_template.json

# Scan the template for common secret patterns
grep -Ei 'password|passwd|secret|apikey|api_key|token|credential|private_key' 
  stack_template.json

# List stack parameters — DefaultValue shown even for NoEcho params in some API versions
aws cloudformation describe-stacks --stack-name TargetStack 
  --query 'Stacks[0].Parameters[*].{Key:ParameterKey,Value:ParameterValue}' 
  --output table

# List stack outputs — may contain access keys, generated passwords, connection strings
aws cloudformation describe-stacks --stack-name TargetStack 
  --query 'Stacks[0].Outputs[*].{Key:OutputKey,Value:OutputValue}' 
  --output table

# Enumerate auto-created CF template S3 buckets (prefixed cf-templates-)
aws s3 ls | grep cf-templates-

# Download and scan all templates from the CF template bucket
BUCKET="cf-templates-ACCOUNTID-REGION"
aws s3 sync s3://${BUCKET}/ ./cf_templates/ --no-sign-request 2>/dev/null || 
aws s3 sync s3://${BUCKET}/ ./cf_templates/

# Run truffleHog on downloaded templates
trufflehog filesystem ./cf_templates/ --json | 
  python3 -c "import sys,json; [print(json.dumps(r,indent=2)) for r in
              (json.loads(l) for l in sys.stdin) if r.get('Verified')]"

Security Assessment Methodology

  1. Enumerate all stacks. Run aws cloudformation list-stacks with all non-deleted status filters. Note creation dates — older stacks are more likely to predate Secrets Manager adoption and contain hardcoded values.
  2. Retrieve templates and scan for secrets. For each stack, call GetTemplate and run truffleHog or gitleaks against the output. Pay particular attention to UserData fields (base64-decode them first) and Parameters.Default values.
  3. Check stack outputs and events. describe-stacks Outputs section may contain generated credentials. Stack events (describe-stack-events) can show parameter values that were passed at creation time and logged before NoEcho was respected.
  4. Enumerate the CF template S3 bucket. Find the bucket with aws s3 ls | grep cf-templates-. Check its bucket policy and ACL — if it is publicly readable, every template version ever deployed is accessible without authentication.
  5. Check change sets. aws cloudformation list-change-sets and describe-change-set may expose parameter values provided during update operations.
  6. Remediate: Replace all plaintext parameter defaults with {{resolve:secretsmanager:...}} dynamic references. Remove any Outputs that expose secret values. Enable S3 Block Public Access on the CF template bucket. Rotate any credentials found during the assessment and audit CloudTrail for evidence they were accessed.

Common Assessment Errors

  • Assuming NoEcho means encrypted. NoEcho only suppresses display in the console and certain API responses. GetTemplate still returns the raw template with the plaintext value. Assessors who mark NoEcho parameters as "protected" are wrong.
  • Missing UserData base64 encoding. UserData is base64-encoded in the template. Tools scanning for plaintext secrets will miss credentials inside UserData unless the field is decoded first. Always pipe UserData through base64 -d before scanning.
  • Ignoring nested stacks. CloudFormation supports nested stacks via AWS::CloudFormation::Stack resources. The parent template may be clean while a child template contains secrets. Recursively retrieve templates for all nested stack resources.
  • Not checking deleted stacks. list-stacks with filter DELETE_COMPLETE returns deleted stacks. Their templates may still exist in the S3 bucket and GetTemplate may still work for recently deleted stacks. Old secrets in deleted stacks may still be valid.
  • Overlooking Outputs in automation pipelines. CI/CD pipelines that call describe-stacks to read Outputs and pass values to downstream jobs may be logging secret values in build logs. Check CloudTrail for DescribeStacks calls from pipeline roles.
  • Forgetting that Checkov can pre-empt this. Run checkov -d ./templates --check CKV_AWS_124 on the IaC repository. Catching hardcoded secrets before deployment is orders of magnitude cheaper than post-compromise credential rotation.

NICE Framework Alignment

Code Knowledge/Skill/Task Statement How This Card Develops It
K0053 Knowledge of security risk management processes Quantifying the risk of credential exposure in IaC artifacts: the durability of CloudFormation storage means secrets persist long after rotation
K0167 Knowledge of system administration, network, and OS hardening techniques Hardening IaC pipelines by replacing hardcoded secrets with Secrets Manager dynamic references and enforcing pre-commit scanning
S0073 Skill in conducting vulnerability scans and recognizing vulnerabilities Applying truffleHog and Checkov to CloudFormation templates to detect plaintext credentials before and after deployment
T0144 Conduct penetration testing as required for new or updated applications Systematically retrieving and analysing CloudFormation templates and outputs during an AWS penetration test to harvest credentials
T0395 Write code to address security vulnerabilities Refactoring CloudFormation templates to use {{resolve:secretsmanager}} dynamic references, eliminating plaintext credential storage

Further Reading

  • AWS CloudFormation Security Best Practices — AWS Documentation (docs.aws.amazon.com/cloudformation)
  • Hacking the Cloud: CloudFormation Enumeration — Nick Frichette (hackingthe.cloud)
  • Secrets Management with AWS Secrets Manager — AWS re:Invent 2022 session SEC317 (AWS Events)

Challenge Lab

Reinforce your learning with a hands-on generated challenge based on this card's competency.