Plaintext or hard-coded secrets can be found in many resources throughout AWS if there is poor hygiene in the management of secrets.
CloudFormation
CloudFormation is an AWS infrastructure-as-code solution written in JSON or YAML
# provides details of the stacks including parameter key/valuesaws--regionus-east-1cloudformationdescribe-stacks# view the source code for a specific stackaws--regionus-east-1cloudformationget-template--stack-nameexecution|jq-r'.TemplateBody'
EC2 Instances
User-data
Secrets can end up hard-coded in EC2 user-data and can easily be discovered either with the action ec2:DescribeInstanceAttributeor by querying the IMDS service
AWS CLI
# using the aws cli aws--regionus-west-2ec2describe-instance-attribute--attributeuserData--instance-idi-0aa2215a0322ec638|jq-r'.UserData.Value'|base64--decode# outputecho"aws_access_key_id = AKIAZxxxxxxxxxx">>~/ec2-user/.aws/credentialsecho"aws_secret_access_key = T2a4SjDnqsPUxxxxxxx">>~/ec2-user/.aws/credentials
IMDSv1
# querying IMDSv1 (code execution on the instance is required)curlhttp://169.254.169.254/latest/user-data# output echo"aws_access_key_id = AKIAZxxxxxxxxxx">>~/ec2-user/.aws/credentialsecho"aws_secret_access_key = T2a4SjDnqsPUxxxxxxx">>~/ec2-user/.aws/credentials
IMDSv2
Version 2 of IMDS requires obtaining a token first
# querying IMDSv2 (code execution on the instance is required)TOKEN=`curl-XPUT "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/user-data# output echo"aws_access_key_id = AKIAZxxxxxxxxxx">>~/ec2-user/.aws/credentialsecho"aws_secret_access_key = T2a4SjDnqsPUxxxxxxx">>~/ec2-user/.aws/credentials
EC2 Launch Templates
EC2 Launch Templates allow for defining consistent configurations (Security Groups, IMDS, Instance types, User Data, etc.) for any EC2 that uses the template
# view the launch templateaws--regionus-west-2ec2describe-launch-template-versions--launch-template-idlt-12k4n9f933873nkdn--versions1{"LaunchTemplateVersions": [ {"LaunchTemplateId":"lt-12k4n9f933873nkdn","LaunchTemplateName":"my-ec2-template","VersionNumber":1,"VersionDescription":"my-ec2-template","CreateTime":"2025-1-03T11:32:25+00:00","CreatedBy":"arn:aws:iam::111111111111:dev_user","DefaultVersion":true,"LaunchTemplateData":{"UserData":"ZWNobyAiYXdzX2FjY2Vzc19rZXlfaWQgPSBBS0lBWnh4eHh4eHh4eHgiID4+IH4vZWMyLXVzZXIvLmF3cy9jcmVkZW50aWFscwplY2hvICJhd3Nfc2VjcmV0X2FjY2Vzc19rZXkgPSBUMmE0U2pEbnFzUFV4eHh4eHh4IiA+PiB+L2VjMi11c2VyLy5hd3MvY3JlZGVudGlhbHM=" }}
# decode the user dataaws--regionus-west-2ec2describe-launch-template-versions--launch-template-idlt-12k4n9f933873nkdn--versions1|jq-r'.LaunchTemplateVersions[].LaunchTemplateData.UserData'|base64--decode# outputecho"aws_access_key_id = AKIAZxxxxxxxxxx">>~/ec2-user/.aws/credentialsecho"aws_secret_access_key = T2a4SjDnqsPUxxxxxxx">>~/ec2-user/.aws/credentials
EBS Snapshots
EBS Snapshots are backups of EC2 instances and may have secrets and credentials stored on them
EBS snapshots are regional so make sure to check each region
# find snapshots in your accountaws--regionus-west-2ec2describe-snapshots--owner-idsself
Lambda
Environment Variables
Environment variables are commonly used for storing data used by the lambda function
# list all functions and return their env varsaws--regionus-east-1lambdalist-functions|jq-r'.Functions[].Environment.Variables'{"ACCESS_KEY_ID":"AKIA.....","SECRET_ACCESS_KEY":"SetQ...."}{"RDS_HOST":"mydatabase.sflwnf3l22n3.us-east-1.rds.amazonaws.com","RDS_PASSWORD":"superSecret","RDS_USER":"root"}
Functions
The code of the function may also contain information
# download a function's codeaws--regionus-east-1lambdaget-function--function-namemyfunction--query'Code.Location'--outputtext|xargscurl-olambda_func.zipunziplambda_func.zip
RDS Snapshots
RDS Snapshots are backups of RDS instances and may contain valuable data
RDS snapshots are regional so make sure to check each region
# find snapshots in your accountawsrdsdescribe-db-snapshots--regionus-west-2
# get secret (can only decrypt if you have permission to the kms key)aws--regionus-west-2secretsmanagerget-secret-value--secret-idproduction_database_password{"ARN":"arn:aws:secretsmanager:us-west-2:111111111111:secret:production_database_password-BOcLnM","Name":"production_database_password","VersionId":"2ad27539-26a6-40fc-b412-774e749e6d80","SecretString":"{\"database_password\":\"l;3lj2l3nr23nrlnslfio3\"}","VersionStages": ["AWSCURRENT" ],"CreatedDate":"2025-01-03T18:43:58.798000-07:00"}
SSM
Documents
SSM Documents allow you to run automations and commands on EC2s and may contain sensitive data
# find ssm documents in your accountawsssmlist-documents|jq-r'.DocumentIdentifiers[] | select(.Owner | contains("111111111111")) | (.Name)'
Parameters
You can reference Systems Manager parameters in your scripts, commands, SSM documents, and configuration and automation workflows
# list ssm parametersaws--regionus-west-2ssmdescribe-parameters{"Parameters": [ {"Name":"uninstall_key","ARN":"arn:aws:ssm:us-west-2:111111111111:parameter/uninstall_key","Type":"SecureString","KeyId":"alias/aws/ssm","LastModifiedDate":"2025-01-03T18:36:21.900000-07:00","LastModifiedUser":"arn:aws:iam::111111111111:user/dev_user","Description":"key used to uninstall our EDR","Version":1,"Tier":"Standard","Policies": [],"DataType":"text" } ]}
# get parameter (can only decrypt if you have permission to the kms key)aws--regionus-west-2ssmget-parameter--nameuninstall_key--with-decryption{"Parameter":{"Name":"uninstall_key","Type":"SecureString","Value":"34n34n393nndg0sng4","Version":1,"LastModifiedDate":"2025-01-03T18:36:21.900000-07:00","ARN":"arn:aws:ssm:us-west-2:111111111111:parameter/uninstall_key","DataType":"text" }}
Terraform State
While not an AWS resource, Terraform State files are commonly stored in AWS S3 buckets
If the data is not encrypted and/or you have access to decrypt the data, Terraform State files often contain secrets, credentials, and information about the cloud environment
# example of downloading terraform state from file awss3cps3://myterraformstatebucket/prod/prod-account-a/terraform.tfstate.# output state to json to see sensitive valuesterraformshow-json|jq{"format_version":"1.0","terraform_version":"1.5.7","values":{"root_module":{"resources": [ {"address":"aws_iam_access_key.admin","mode":"managed","type":"aws_iam_access_key","name":"admin","provider_name":"registry.terraform.io/hashicorp/aws","schema_version":0,"values":{"create_date":"2025-01-04T01:17:57Z","encrypted_secret":null,"encrypted_ses_smtp_password_v4":null,"id":"AKIA[...]","key_fingerprint":null,"pgp_key":null,"secret":"dfY0XUrA[...]","ses_smtp_password_v4":"BBPzJ[...]","status":"Active","user":"admin" },"sensitive_values":{"secret":true,"ses_smtp_password_v4":true } } ] } }} # you can also just read the state file since it's jsoncatterraform.tfstate|jq