Deep Enumeration - baeziy/AWSault GitHub Wiki

Deep Enumeration

Deep enumeration is Phase 2 of --godeep. It takes resources discovered during the surface scan and pulls their detailed configurations.

Overview

The surface scan tells you what services you can access. Deep enumeration tells you what's actually there — the full configs, policies, secrets, and relationships between resources.

awsault --godeep

Enumeration chains

AWSault runs 11 resource-specific chains. Each chain takes the surface scan results and makes targeted follow-up API calls to pull detailed data.

S3 (chain_s3)

For each discovered bucket:

  • Bucket ACL (get_bucket_acl)
  • Bucket policy (get_bucket_policy)
  • Public access block configuration (get_public_access_block)
  • Server-side encryption configuration (get_bucket_encryption)
  • Versioning status (get_bucket_versioning)
  • Logging configuration (get_bucket_logging)
  • Website hosting configuration (get_bucket_website)

IAM Users (chain_iam_users)

For each discovered user:

  • Access keys with creation dates and status (list_access_keys)
  • MFA devices (list_mfa_devices)
  • Inline policies with full policy documents (list_user_policies + get_user_policy)
  • Attached managed policies with full policy documents (list_attached_user_policies + get_policy + get_policy_version)
  • Group memberships (list_groups_for_user)
  • Login profile / console access status (get_login_profile)

IAM Roles (chain_iam_roles)

For each discovered role:

  • Trust policy / assume role policy document
  • Inline policies with full policy documents (list_role_policies + get_role_policy)
  • Attached managed policies with full policy documents (list_attached_role_policies + get_policy + get_policy_version)

IAM Self / Identity Recon (chain_iam_self)

This is the core recon chain. See Identity Recon for full details. It:

  • Identifies whether you're a user or a role
  • Enumerates every policy on your principal (inline, attached, group-inherited)
  • Fetches full policy documents with Allow/Deny statements
  • Enumerates all versions of managed policies (for privesc via SetDefaultPolicyVersion)
  • Discovers assumable roles by scanning your policies for sts:AssumeRole and checking trust policies
  • Enumerates policies on each assumable role
  • Detects 14 known privilege escalation paths

Lambda (chain_lambda)

For each discovered function:

  • Full function configuration including environment variables
  • Resource-based policy (get_policy)
  • Function tags

EC2 User Data (chain_ec2_userdata)

For each discovered instance:

  • Instance user data script (describe_instance_attribute with Attribute=userData)
  • Base64 decoded automatically
  • Often contains bootstrap scripts with hardcoded credentials

CloudTrail (chain_cloudtrail)

For each discovered trail:

  • Trail status — is it actually logging? (get_trail_status)
  • Event selectors — what's being recorded? (get_event_selectors)

KMS (chain_kms)

For each discovered key:

  • Key metadata (describe_key)
  • Key policy (get_key_policy)
  • Rotation status (get_key_rotation_status)

ECS (chain_ecs)

For each task definition (capped at 50):

  • Full task definition including container definitions
  • Environment variables and secrets references in each container

CloudFormation (chain_cloudformation)

For each active stack:

  • Full stack details (describe_stacks)
  • Stack outputs (often contain endpoints, ARNs, connection strings)
  • Stack parameters (may contain passwords, API keys)

RDS (chain_rds)

For each discovered DB instance:

  • Engine type and version
  • Public accessibility status
  • Storage encryption status
  • Security groups
  • Backup retention period
  • Multi-AZ deployment status

Concurrency

All 11 chains run in parallel using a thread pool (default 10 workers). Each chain runs independently — if one fails or times out, the others continue.

Data flow

Surface Scan Results
        │
        ├── chain_s3 ──────────────> S3 bucket configs
        ├── chain_iam_users ───────> User policies, keys, MFA
        ├── chain_iam_roles ───────> Role policies, trust docs
        ├── chain_iam_self ────────> Identity map, privesc paths
        ├── chain_lambda ──────────> Function configs, env vars
        ├── chain_ec2_userdata ────> Bootstrap scripts
        ├── chain_cloudtrail ──────> Trail status
        ├── chain_kms ─────────────> Key policies, rotation
        ├── chain_ecs ─────────────> Task def env vars
        ├── chain_cloudformation ──> Stack outputs, params
        └── chain_rds ─────────────> DB configs
                │
                v
        Deep Results Dict ──> Security Audit ──> Findings

Managed policy document fetching

When AWSault encounters a managed policy (customer or AWS-managed), it:

  1. Calls get_policy to get the policy ARN and default version ID
  2. Calls get_policy_version to get the actual JSON policy document
  3. Parses the document into simplified statements (Effect, Actions, Resources, Conditions)
  4. For the identity recon chain: also enumerates all non-default versions via list_policy_versions

This means you see the actual permissions, not just the policy name.