Skip to content
HackIndex logo

HackIndex

AWS Account ID and IAM Discovery

3 min read May 24, 2026

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:

┌──(kali㉿kali)-[~]
└─$ aws s3api get-bucket-acl --bucket $BUCKET --no-sign-request
{
    "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:

┌──(kali㉿kali)-[~]
└─$ aws ec2 describe-images --filters "Name=name,Values=*$COMPANY*" --no-sign-request --region us-east-1
{
    "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:

┌──(kali㉿kali)-[~]
└─$ grep -r "role-to-assume" .github/workflows/
- 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:

┌──(kali㉿kali)-[~]
└─$ aws sts get-access-key-info --access-key-id $AWS_ACCESS_KEY_ID
{
    "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.