AWS Account ID and IAM Discovery
Before touching any AWS API with credentials, collect what you can passively. Account IDs, IAM role names, and ARN patterns narrow your attack surface and inform later privilege escalation attempts.
Account ID from Public S3 Buckets
Public S3 bucket ACL responses leak the account ID of the bucket owner. If you found a public bucket during S3 recon:
{
"Owner": {
"DisplayName": "company-aws",
"ID": "79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be"
}
}
Explain command
| --no-sign-request | Make request without credentials. Works on public buckets. |
The ID is a canonical user ID, not the account ID directly — but it can be correlated. For the numeric account ID, check SNS topic ARNs or other public resources.
Account ID from Public AMIs
Organizations frequently publish AMIs with their account ID embedded in the ARN. Search for AMIs by company name or known product:
{
"ImageId": "ami-0abc123",
"OwnerId": "123456789012",
"Name": "company-app-server-2024"
}
Explain command
| --no-sign-request | Query public AMIs without credentials. |
| --region us-east-1 | Repeat across regions — AMIs are region-specific. |
OwnerId is the 12-digit AWS account ID.
Account ID from Public ECR Repositories
Public ECR image URIs contain the account ID:
123456789012.dkr.ecr.us-east-1.amazonaws.com/repo-name
Search Docker Hub, GitHub Actions logs, CI/CD configs, and public documentation for ECR image references.
Account ID from Exposed ARNs
ARNs appear in:
GitHub Actions workflow YAML (
role-to-assume: arn:aws:iam::123456789012:role/...)CloudFormation templates in public repos
Terraform state files accidentally committed
Job listings and blog posts referencing AWS infrastructure
Error messages returned by web applications running on AWS
Search GitHub:
"arn:aws:iam" "$COMPANY" filename:.yml
"arn:aws:iam" "$DOMAIN"
"role-to-assume" "$COMPANY"
IAM Role Names from GitHub Actions
GitHub Actions workflows that assume AWS roles via OIDC expose role ARNs directly in the repo:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeployRole
aws-region: us-east-1
This gives you the account ID and an exact role name. The role may be assumable if the trust policy is overly permissive. See OIDC Federation Abuse for follow-up.
Error-Based Account ID Leak
The sts:GetAccessKeyInfo API returns the account ID for any access key ID — no secret needed, and access keys are not secret identifiers:
{
"Account": "123456789012"
}
If you found an access key ID (but not the secret) in source code or logs, this confirms which account it belongs to.
Metadata from Web Applications
Applications hosted on EC2 that return verbose AWS error messages often include account IDs and ARNs in stack traces. Trigger errors on:
Missing parameters
Invalid input to endpoints that call AWS APIs
500 errors that expose IAM permission denied messages
A AccessDeniedException response typically contains the full ARN of the calling principal:
User: arn:aws:sts::123456789012:assumed-role/WebAppRole/i-0abc123 is not authorized to perform: s3:GetObject
This leaks: account ID, role name, and EC2 instance ID.
Was this helpful?
Your feedback helps improve this page.