Last active
June 6, 2025 17:31
-
-
Save nullenc0de/f8a569ecfcf35b39867d488b3a560bbd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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