Browse CTFs New CTF Sign in

AWS Secrets Manager Access Control Weaknesses: Scoping IAM Policies for GetSecretValue

osint_collection Difficulty 1–5 30 min certifiable

Theory

Why This Matters

In 2021, researchers analysing a compromised AWS environment found that a single EC2 instance profile with secretsmanager:GetSecretValue on Resource: "*" had been used to exfiltrate credentials for a production database, a payment processing API key, and a third-party analytics service — all from a single compromised instance that nominally served a marketing microservice with no legitimate need for any of those secrets. AWS Secrets Manager centralises secret storage, but centralisation without access control creates a single high-value target: any principal with broad GetSecretValue permissions can drain the entire secret store. The service provides the tooling for granular access control; the vulnerability is in how IAM policies are written.

Core Concept

AWS Secrets Manager stores, rotates, and controls access to secrets such as database credentials, API keys, and OAuth tokens. Secrets are identified by a secret ARN and an optional human-readable name. Access is controlled at two levels: IAM identity-based policies (who can call which Secrets Manager APIs) and resource-based policies (a per-secret policy controlling cross-account access or providing additional conditions).

Key API actions for access control analysis: - secretsmanager:GetSecretValue — retrieves the plaintext or binary secret value. This is the high-value action that must be tightly scoped. - secretsmanager:ListSecrets — enumerates all secrets in the account (names, ARNs, metadata — not values). An attacker with only this permission can map the secret store. - secretsmanager:DescribeSecret — retrieves metadata including rotation schedule and resource policy. Does not expose the secret value. - secretsmanager:PutSecretValue / UpdateSecret — writes a new secret version. An attacker with write access can poison a secret to cause application malfunction or inject credentials they control.

Principle of least privilege for Secrets Manager means each application role should have GetSecretValue scoped to only the specific secret ARNs it needs, not to Resource: "*". AWS recommends using secret name prefixes (e.g., prod/myapp/*) and Resource ARN patterns to scope access while remaining maintainable as new secrets are added.

Automatic rotation is a key Secrets Manager feature: Lambda functions rotate secrets on a schedule, eliminating long-lived static credentials. A secret without rotation configured is a finding: static credentials exposed in a breach remain valid indefinitely.

Technical Deep-Dive

# Enumerate all secrets in the account (requires secretsmanager:ListSecrets)
aws secretsmanager list-secrets 
  --query 'SecretList[*].{Name:Name,ARN:ARN,Rotation:RotationEnabled,LastRotated:LastRotatedDate}' 
  --output table

# Describe a specific secret — metadata only, no value exposed
aws secretsmanager describe-secret --secret-id "prod/myapp/database" 
  --query '{ARN:ARN,Rotation:RotationEnabled,ResourcePolicy:exists(SecretValue)}'

# Retrieve the resource-based policy of a secret
aws secretsmanager get-resource-policy --secret-id "prod/myapp/database" 
  --query 'ResourcePolicy' --output text | python3 -m json.tool

# Attempt to retrieve the secret value (tests if current principal has access)
aws secretsmanager get-secret-value --secret-id "prod/myapp/database" 
  --query '{Name:Name,SecretString:SecretString}' --output json

# Check which IAM policies grant GetSecretValue with wildcard resources
# (run as admin — requires iam:GetPolicyVersion)
aws iam list-policies --scope Local 
  --query 'Policies[*].{Name:PolicyName,Arn:Arn}' --output text | 
while read name arn; do
  version=$(aws iam get-policy --policy-arn "$arn" 
    --query 'Policy.DefaultVersionId' --output text)
  doc=$(aws iam get-policy-version --policy-arn "$arn" 
    --version-id "$version" --query 'PolicyVersion.Document' --output text)
  if echo "$doc" | grep -q 'GetSecretValue'; then
    resource=$(echo "$doc" | python3 -c 
      "import sys,json; doc=json.loads(sys.stdin.read())
[print(s.get('Resource')) for s in doc.get('Statement',[]) if 'GetSecretValue' in str(s.get('Action','))]")
    echo "Policy: $name  Resource: $resource"
  fi
done

# Simulate whether a role can access a specific secret
aws iam simulate-principal-policy 
  --policy-source-arn "arn:aws:iam::ACCOUNT_ID:role/MarketingServiceRole" 
  --action-names secretsmanager:GetSecretValue 
  --resource-arns "arn:aws:secretsmanager:us-east-1:ACCOUNT_ID:secret:prod/payments/stripe-key" 
  --query 'EvaluationResults[*].{Action:EvalActionName,Decision:EvalDecision}' 
  --output table

Security Assessment Methodology

  1. Enumerate all secrets. aws secretsmanager list-secrets shows names, ARNs, and rotation status. Secrets with RotationEnabled: false and old LastChangedDate values are static credentials — a finding independent of access control.
  2. Identify which principals can call GetSecretValue. Search IAM policies (inline and managed) for secretsmanager:GetSecretValue statements. Pay attention to Resource values — "*" is the highest-severity finding. Use iam simulate-principal-policy to confirm effective access.
  3. Check resource-based secret policies. Retrieve the resource policy for each secret. Cross-account principals or "Principal": "*" in a secret policy warrant immediate investigation.
  4. Test access from each application role. For each application role in scope, attempt GetSecretValue against secrets that role should not be able to access (e.g., a web tier role attempting to read payment processor credentials). Document successful retrievals.
  5. Check for ListSecrets exposure. Even without GetSecretValue, an attacker with ListSecrets can enumerate all secret names, revealing the application architecture, third-party integrations, and naming conventions. Scope ListSecrets to application-specific prefixes.
  6. Remediate by scoping all GetSecretValue policies to specific secret ARNs or ARN patterns matching the application's required secrets. Enable automatic rotation for all database and API key secrets. Add resource-based policies with aws:SourceVpc or aws:PrincipalAccount conditions where applicable.

Common Assessment Errors

  • Only testing GetSecretValue. PutSecretValue and UpdateSecret are equally dangerous — an attacker who can write a secret can inject credentials they control, causing applications to authenticate to attacker-controlled services. Always check write permissions.
  • Ignoring the Lambda rotation function. The Lambda function used for secret rotation itself has an execution role. If that role has GetSecretValue on all secrets (a common pattern for "simplicity"), it is an escalation path via Lambda code injection.
  • Missing KMS key access. Secrets Manager encrypts secrets using KMS. An attacker with kms:Decrypt on the key used to encrypt secrets, combined with direct access to the Secrets Manager storage bucket, could potentially decrypt secrets without going through the Secrets Manager API. Audit KMS key policies for kms:Decrypt grants.
  • Not checking CloudTrail for prior GetSecretValue calls. Even after discovering a misconfiguration, check whether it was exploited. CloudTrail logs GetSecretValue API calls with caller identity, timestamp, and secret name. Historical access by unexpected principals is evidence of a breach.
  • Treating the secret name as non-sensitive. Secret names are returned by ListSecrets and visible in CloudTrail without requiring GetSecretValue. Names like prod/database/admin-password confirm the existence of an admin database credential. Use generic naming conventions and treat ListSecrets access as sensitive.

NICE Framework Alignment

Code Knowledge/Skill/Task Statement How This Card Develops It
K0053 Knowledge of security risk management processes Evaluating Secrets Manager access risk: centralised secret storage amplifies the impact of over-broad IAM policies, making access control critical
K0167 Knowledge of system administration, network, and OS hardening techniques Hardening Secrets Manager deployments: ARN-scoped GetSecretValue policies, automatic rotation, KMS CMK with minimal decrypt grants
S0073 Skill in conducting vulnerability scans and recognizing vulnerabilities Using list-secrets, simulate-principal-policy, and IAM policy scanning to identify roles with unauthorised access to secrets beyond their application scope
T0144 Conduct penetration testing as required for new or updated applications Testing Secrets Manager access from application roles during AWS assessments to identify credential over-exposure and lateral movement paths
T0395 Write code to address security vulnerabilities Writing least-privilege IAM policies scoping secretsmanager:GetSecretValue to specific secret ARNs using prefix-based Resource patterns

Further Reading

  • AWS Secrets Manager Best Practices — AWS Documentation (docs.aws.amazon.com/secretsmanager/latest/userguide/best-practices.html)
  • Hacking the Cloud: Secrets Manager Enumeration — Nick Frichette (hackingthe.cloud)
  • AWS Security Cookbook — Heartin Kanikathottu, Chapter 5: Secrets Management (Packt Publishing)

Challenge Lab

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