Skip to content

Instantly share code, notes, and snippets.

@nullenc0de
Last active June 6, 2025 17:31
Show Gist options
  • Save nullenc0de/f8a569ecfcf35b39867d488b3a560bbd to your computer and use it in GitHub Desktop.
Save nullenc0de/f8a569ecfcf35b39867d488b3a560bbd to your computer and use it in GitHub Desktop.
id: aws-iam-privilege-escalation
info:
name: AWS IAM Privilege Escalation Vectors
author: nullenc0de
severity: critical
description: |
Detects AWS IAM policies, credentials, metadata, and configurations that allow privilege escalation paths.
Covers exposed credentials, overly permissive IAM policies, misconfigured metadata services, vulnerable role assumptions, and user-data scripts.
reference:
- https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/
- https://bishopfox.com/blog/privilege-escalation-in-aws
- https://hackingthe.cloud/aws/exploitation/iam-privilege-escalation/
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
cvss-score: 9.9
cwe-id: CWE-269
tags: aws, iam, privilege-escalation, cloud, critical
http:
- method: GET
path:
- "{{BaseURL}}/.aws/config"
- "{{BaseURL}}/.aws/credentials"
- "{{BaseURL}}/aws/config"
- "{{BaseURL}}/aws/credentials"
- "{{BaseURL}}/config/aws/config"
- "{{BaseURL}}/config/aws/credentials"
- "{{BaseURL}}/backup/.aws/config"
- "{{BaseURL}}/backup/.aws/credentials"
- "{{BaseURL}}/tmp/.aws/config"
- "{{BaseURL}}/tmp/.aws/credentials"
- "{{BaseURL}}/var/log/aws/config"
- "{{BaseURL}}/opt/aws/config"
- "{{BaseURL}}/home/ubuntu/.aws/config"
- "{{BaseURL}}/home/ec2-user/.aws/config"
- "{{BaseURL}}/root/.aws/config"
- "{{BaseURL}}/.env"
- "{{BaseURL}}/config/.env"
- "{{BaseURL}}/backup/.env"
- "{{BaseURL}}/debug/.aws/credentials"
- "{{BaseURL}}/archive/config/aws.json"
- "{{BaseURL}}/laravel/.env" # Framework-specific path
headers:
User-Agent: "Mozilla/5.0 (compatible; Nuclei Scanner)"
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: word
part: body
words:
- "aws_access_key_id"
- "aws_secret_access_key"
- "[default]"
condition: or
- type: regex
part: body
regex:
- "(AKIA|ASIA)[0-9A-Z]{16}" # AWS Access Keys
- "([A-Za-z0-9/+=]{40})" # Secret Access Keys
- type: word
part: body
words:
- "<html>"
- "<head>"
- "<body>"
condition: or
negative: true # Exclude HTML content
extractors:
- type: regex
part: body
regex:
- "(AKIA[0-9A-Z]{16})" # AWS Access Keys
- "([A-Za-z0-9/+=]{40})" # Secret Access Keys
- "(arn:aws:iam::[0-9]{12}:role/[A-Za-z0-9_+=,.@-]+)" # Role ARNs
- method: PUT
path:
- "{{BaseURL}}/169.254.169.254/latest/api/token"
- "{{BaseURL}}/v1/meta-data/api/token"
- "{{BaseURL}}/metadata/v1/api/token"
headers:
User-Agent: "Mozilla/5.0 (compatible; Nuclei Scanner)"
X-aws-ec2-metadata-token-ttl-seconds: "21600"
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: regex
part: body
regex:
- "^[A-Za-z0-9/+=]{50,}$" # AWS tokens are typically 50+ chars, base64-like
- type: word
part: body
words:
- "<html>"
- "<head>"
- "<body>"
condition: or
negative: true # Exclude HTML content
extractors:
- type: regex
name: metadata_token
part: body
regex:
- "^([A-Za-z0-9/+=]{50,})$"
- method: GET
path:
- "{{BaseURL}}/v1/meta-data/iam/security-credentials/"
- "{{BaseURL}}/latest/meta-data/iam/security-credentials/"
- "{{BaseURL}}/169.254.169.254/latest/meta-data/iam/security-credentials/"
- "{{BaseURL}}/metadata/v1/instance/service-accounts/default/token"
headers:
User-Agent: "Mozilla/5.0 (compatible; Nuclei Scanner)"
X-aws-ec2-metadata-token: "{{metadata_token}}"
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: word
part: body
words:
- "AccessKeyId"
- "SecretAccessKey"
- "Token"
condition: and
- type: word
part: header
words:
- "text/html"
condition: and
negative: true # Exclude HTML responses
- type: word
part: body
words:
- "<html>"
- "<head>"
- "<body>"
condition: or
negative: true # Exclude HTML content
extractors:
- type: regex
part: body
regex:
- '"AccessKeyId".*"([^"]+)"'
- '"SecretAccessKey".*"([^"]+)"'
- '"Token".*"([^"]+)"'
- method: GET
path:
- "{{BaseURL}}/iam/policy"
- "{{BaseURL}}/iam/policies"
- "{{BaseURL}}/aws/iam/policy.json"
- "{{BaseURL}}/policies/iam-policy.json"
- "{{BaseURL}}/config/iam-policy.json"
- "{{BaseURL}}/terraform/iam.tf"
- "{{BaseURL}}/cloudformation/iam.yaml"
- "{{BaseURL}}/cloudformation/iam.json"
- "{{BaseURL}}/backup/iam-policy.json"
- "{{BaseURL}}/tfstate/iam.tfstate" # Terraform state file
headers:
User-Agent: "Mozilla/5.0 (compatible; Nuclei Scanner)"
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: word
part: body
words:
- '"Effect": "Allow"'
- '"Action":'
- '"Resource":'
condition: and
- type: regex
part: body
regex:
- '"Action".*"\\*"' # Any wildcard actions
- '"Resource".*"\\*"' # Wildcard resources
- '"iam:\\*"' # IAM wildcard
- '"s3:\\*"' # S3 wildcard
- '"ec2:\\*"' # EC2 wildcard
condition: or
- type: word
part: body
words:
- "<html>"
- "<head>"
- "<body>"
condition: or
negative: true # Exclude HTML content
extractors:
- type: regex
part: body
regex:
- '"Action".*"([^"]*\\*[^"]*)"'
- '"Resource".*"(\\*)"'
- '"Principal".*"(\\*)"'
- "(arn:aws:iam::[0-9]{12}:role/[A-Za-z0-9_+=,.@-]+)"
- method: POST
path:
- "{{BaseURL}}/api/aws/sts/assume-role"
- "{{BaseURL}}/aws/assume-role"
- "{{BaseURL}}/sts/assume-role"
headers:
User-Agent: "Mozilla/5.0 (compatible; Nuclei Scanner)"
Content-Type: "application/json"
body: |
{
"RoleArn": "arn:aws:iam::123456789012:role/AdminRole",
"RoleSessionName": "nuclei-test-session"
}
matchers-condition: and
matchers:
- type: status
status:
- 200
- 403 # Indicates role exists but may require specific permissions
- type: word
part: body
words:
- "AccessKeyId"
- "SecretAccessKey"
- "SessionToken"
condition: or
- type: word
part: body
words:
- "<html>"
- "<head>"
- "<body>"
condition: or
negative: true # Exclude HTML content
extractors:
- type: regex
part: body
regex:
- '"AccessKeyId".*"([^"]+)"'
- '"SecretAccessKey".*"([^"]+)"'
- '"SessionToken".*"([^"]+)"'
- method: GET
path:
- "{{BaseURL}}/user-data"
- "{{BaseURL}}/userdata"
- "{{BaseURL}}/user_data"
- "{{BaseURL}}/169.254.169.254/latest/user-data"
- "{{BaseURL}}/metadata/v1/instance/attributes/user-data"
- "{{BaseURL}}/scripts/bootstrap.sh" # Common user-data script path
- "{{BaseURL}}/config/startup.sh" # Application startup script
headers:
User-Agent: "Mozilla/5.0 (compatible; Nuclei Scanner)"
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: regex
part: body
regex:
- "(?i)(aws_access_key_id|aws_secret_access_key)"
- "(AKIA[0-9A-Z]{16})"
- "aws.*configure"
- "export.*AWS_"
condition: or
- type: word
part: body
words:
- "<html>"
- "<head>"
- "<body>"
condition: or
negative: true # Exclude HTML content
extractors:
- type: regex
part: body
regex:
- "(AKIA[0-9A-Z]{16})"
- "([A-Za-z0-9/+=]{40})"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment