# Enumerate Secrets in AWS

## Secrets Enumeration

Plaintext or hard-coded secrets can be found in many resources throughout AWS if there is poor hygiene in the management of secrets.&#x20;

***

## CloudFormation

* CloudFormation is an AWS infrastructure-as-code solution written in JSON or YAML

{% code overflow="wrap" %}

```bash
# provides details of the stacks including parameter key/values
aws --region us-east-1 cloudformation describe-stacks

# view the source code for a specific stack
aws --region us-east-1 cloudformation get-template --stack-name execution | jq -r '.TemplateBody'
```

{% endcode %}

***

## EC2 Instances

### User-data

* Secrets can end up hard-coded in EC2 user-data and can easily be discovered either with the action `ec2:DescribeInstanceAttribute`or by querying the IMDS service

#### AWS CLI

{% code overflow="wrap" %}

```bash
# using the aws cli 
aws --region us-west-2 ec2 describe-instance-attribute --attribute userData --instance-id i-0aa2215a0322ec638 | jq -r '.UserData.Value' | base64 --decode

# output
echo "aws_access_key_id = AKIAZxxxxxxxxxx" >> ~/ec2-user/.aws/credentials
echo "aws_secret_access_key = T2a4SjDnqsPUxxxxxxx" >> ~/ec2-user/.aws/credentials
```

{% endcode %}

#### IMDSv1

{% code overflow="wrap" %}

```bash
# querying IMDSv1 (code execution on the instance is required)
curl http://169.254.169.254/latest/user-data

# output 
echo "aws_access_key_id = AKIAZxxxxxxxxxx" >> ~/ec2-user/.aws/credentials
echo "aws_secret_access_key = T2a4SjDnqsPUxxxxxxx" >> ~/ec2-user/.aws/credentials
```

{% endcode %}

#### IMDSv2

* Version 2 of IMDS requires obtaining a token first

{% code overflow="wrap" %}

```bash
# querying IMDSv2 (code execution on the instance is required)
TOKEN=`curl -X PUT "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/credentials
echo "aws_secret_access_key = T2a4SjDnqsPUxxxxxxx" >> ~/ec2-user/.aws/credentials
```

{% endcode %}

***

### 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
* So User Data can also be found in the templates&#x20;

{% code overflow="wrap" %}

```bash
# find launch templates
aws --region us-west-2 ec2 describe-launch-templates

{
    "LaunchTemplates": [
        {
            "LaunchTemplateId": "lt-12k4n9f933873nkdn",
            "LaunchTemplateName": "my-ec2-template",
            "CreateTime": "2025-1-03T11:32:25+00:00",
            "CreatedBy": "arn:aws:iam::111111111111:dev_user",
            "DefaultVersionNumber": 1,
            "LatestVersionNumber": 1
        }
    ]
}
```

{% endcode %}

{% code overflow="wrap" %}

```bash
# view the launch template
aws --region us-west-2 ec2 describe-launch-template-versions --launch-template-id lt-12k4n9f933873nkdn --versions 1

{
    "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="
            }
}
```

{% endcode %}

{% code overflow="wrap" %}

```bash
# decode the user data
aws --region us-west-2 ec2 describe-launch-template-versions --launch-template-id lt-12k4n9f933873nkdn --versions 1 | jq -r '.LaunchTemplateVersions[].LaunchTemplateData.UserData' | base64 --decode

# output
echo "aws_access_key_id = AKIAZxxxxxxxxxx" >> ~/ec2-user/.aws/credentials
echo "aws_secret_access_key = T2a4SjDnqsPUxxxxxxx" >> ~/ec2-user/.aws/credentials
```

{% endcode %}

***

## EBS Snapshots

* EBS Snapshots are backups of EC2 instances and may have secrets and credentials stored on them
* See also [Enumerate AWS Public Resources](/cloud-security/aws/aws-offensive-security/aws-attacks-and-techniques/enumerate-aws-public-resources.md#ebs-snapshots)

{% hint style="warning" %}
EBS snapshots are regional so make sure to check each region
{% endhint %}

{% code overflow="wrap" %}

```bash
# find snapshots in your account
aws --region us-west-2 ec2 describe-snapshots --owner-ids self
```

{% endcode %}

***

## Lambda

### Environment Variables

* Environment variables are commonly used for storing data used by the lambda function

{% code overflow="wrap" %}

```bash
# list all functions and return their env vars
aws --region us-east-1 lambda list-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"
}
```

{% endcode %}

### Functions

* The code of the function may also contain information

{% code overflow="wrap" %}

```bash
# download a function's code
aws --region us-east-1 lambda get-function --function-name myfunction --query 'Code.Location' --output text | xargs curl -o lambda_func.zip

unzip lambda_func.zip
```

{% endcode %}

***

## RDS Snapshots

* RDS Snapshots are backups of RDS instances and may contain valuable data
* See also [Enumerate AWS Public Resources](/cloud-security/aws/aws-offensive-security/aws-attacks-and-techniques/enumerate-aws-public-resources.md#rds-snapshots)

{% hint style="warning" %}
RDS snapshots are regional so make sure to check each region
{% endhint %}

{% code overflow="wrap" %}

```bash
# find snapshots in your account
aws rds describe-db-snapshots --region us-west-2
```

{% endcode %}

***

## Secrets Manager

{% code overflow="wrap" %}

```bash
# list secrets 
aws --region us-west-2 secretsmanager list-secrets                             
{
    "SecretList": [
        {
            "ARN": "arn:aws:secretsmanager:us-west-2:111111111111:secret:production_database_password-BOcLnM",
            "Name": "production_database_password",
            "LastChangedDate": "2025-01-03T18:43:58.802000-07:00",
            "Tags": [],
            "SecretVersionsToStages": {
                "2ad27539-26a6-40fc-b412-774e749e6d80": [
                    "AWSCURRENT"
                ]
            },
            "CreatedDate": "2025-01-03T18:43:58.491000-07:00"
        }
    ]
}
```

{% endcode %}

{% code overflow="wrap" %}

```bash
# get secret (can only decrypt if you have permission to the kms key)
aws --region us-west-2 secretsmanager get-secret-value --secret-id production_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"
}
```

{% endcode %}

***

## SSM

### Documents

* SSM Documents allow you to run automations and commands on EC2s and may contain sensitive data
* See also [Enumerate AWS Public Resources](/cloud-security/aws/aws-offensive-security/aws-attacks-and-techniques/enumerate-aws-public-resources.md#ssm-documents)

{% code overflow="wrap" %}

```bash
# find ssm documents in your account
aws ssm list-documents | jq -r '.DocumentIdentifiers[] | select(.Owner | contains("111111111111")) | (.Name)'
```

{% endcode %}

### Parameters

* You can reference Systems Manager parameters in your scripts, commands, SSM documents, and configuration and automation workflows

{% code overflow="wrap" %}

```bash
# list ssm parameters
aws --region us-west-2 ssm describe-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"
        }
    ]
}
```

{% endcode %}

{% code overflow="wrap" %}

```bash
# get parameter (can only decrypt if you have permission to the kms key)
aws --region us-west-2 ssm get-parameter --name uninstall_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"
    }
}
```

{% endcode %}

***

## Terraform State

* While not an AWS resource, Terraform State files are commonly stored in [AWS S3 buckets](https://developer.hashicorp.com/terraform/language/backend/s3)
* 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

{% code overflow="wrap" %}

```bash
# example of downloading terraform state from file 
aws s3 cp s3://myterraformstatebucket/prod/prod-account-a/terraform.tfstate .

# output state to json to see sensitive values
terraform show -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 json
cat terraform.tfstate | jq
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.techwithtyler.dev/cloud-security/aws/aws-offensive-security/aws-attacks-and-techniques/enumerate-secrets-in-aws.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
