Enumerating AWS With Keys
A key starting with AKIA falls out of a Git repo. Now what?
What you will learn
- -Turn a raw access key into a full picture of what it can do
- -Enumerate identity, permissions, and reachable resources without tripping obvious alarms
- -Drive Pacu to automate the whole discovery phase
You found a key. It starts with AKIA, it has a 40-character next to it, and it was sitting in a committed .env file or a public S3 object or a leaked laptop backup. That string is a long-term for an user, and until someone rotates it, it is that user. The whole game now is figuring out who the user is and everything they can reach, before you do anything loud.
Load it into a named profile so you never contaminate your own , then confirm it works.
$aws configure --profile loot$aws sts get-caller-identity --profile lootIf -caller- returns an ARN, the key is live. If it returns InvalidClientTokenId, the key is disabled or fake and you can stop. Keys that begin with ASIA instead of AKIA are temporary session credentials and need a session alongside them, plus they expire, so grab what you can fast.
Map the permissions without asking directly
The obvious move is to call iam:GetUser and iam:ListAttachedUserPolicies and read your own permissions. The problem is that a locked-down user often cannot read its own , and those calls generate clean CloudTrail events that a defender can alarm on. The quieter approach is to enumerate by trial: try calls and record which ones return data versus AccessDenied.
$python3 enumerate-iam.py --access-key AKIA... --secret-key ... --region us-east-1Start with cheap, high-value reads that tell you where the treasure is. Secrets Manager and SSM Store hold and tokens. RDS describes the databases. EC2 describes the fleet. Each of these is one command per .
$aws secretsmanager list-secrets --profile loot --region us-east-1$aws ssm describe-parameters --profile loot --region us-east-1$aws s3 ls --profile loot$aws ec2 describe-instances --profile loot --region us-east-1aws s3 ls with no bucket name lists every bucket the account owns, which is often the single most productive first command. If it returns a list, you have account-wide S3 visibility.
Let Pacu do the sweeping
Doing this by hand across every service and every region is the wrong use of your time past the first few commands. Pacu is Rhino's AWS exploitation , built exactly for this phase. It imports your keys, runs modules, stores results in a database, and flags paths.
$pacu$set_keys$run iam__enum_permissions$run iam__privesc_scaniam__privesc_scan is the payoff module. It takes the permission map and tells you if any of the escalation paths from the IAM lesson, like CreateAccessKey or PassRole, are open to you. That turns "I have some user's key" into "I have a path to admin" in one command.
Enumerating an account from a found key is unauthorized access unless that account is in your engagement or is your own. A found or leaked key does not grant permission to use it. Every call you make lands in CloudTrail with your source IP. Practice on CloudGoat, which hands you deliberately leaked keys to chase, not on keys you stumble across in the wild.
Keep the touch light early. GuardDuty scores anomalous enumeration, and a burst of AccessDenied errors from a new IP is a textbook detection. Read before you write, stay in the regions where you already found resources, and do not fire every module at once on a real engagement.
You recover a key beginning with ASIA and try to use it, getting an error about a missing token. What does the prefix tell you?