TL;DR
- what: Researchers collected hundreds of live AWS access keys from publicly reachable sources, and many of them mapped to IAM principals with administrative rights over entire corporate accounts.
Hundreds of working AWS access keys are sitting in publicly reachable places right now, and a significant share of them do not just read a bucket. They own the account. Researchers who harvested and validated these credentials reported that many resolved to IAM users or roles with administrative permissions, meaning a single 40 character secret is enough to enumerate every resource, create new persistence, disable logging, and bill the victim for whatever the attacker wants to run.
There is no CVE here and no patch to deploy. This is a credential hygiene failure at scale, which is exactly why it keeps working. Attackers do not need to defeat a control. They need a string that somebody committed, pasted, or baked into an artifact and then forgot about.
What was actually found
The recovered credentials were long-lived IAM user keys, the kind that begin with the AKIA prefix and never expire on their own. Unlike temporary STS credentials issued to an EC2 instance profile or an IRSA-bound Kubernetes service account, an AKIA key remains valid until a human deactivates it. Keys created for a one-off migration in 2022 are still authenticating in 2026.
The permission distribution is the part that should worry you. A leaked key scoped to a single S3 prefix is an incident. A leaked key attached to a policy granting the equivalent of AdministratorAccess is a full account compromise with no lateral movement required. Reporting on this research indicates the second category was well represented, not a rare outlier.
⚠️ Assume the window is minutes, not days — Automated scrapers monitor public code hosting event streams continuously. A secret pushed to a public repository is commonly fetched and tested in under a minute. Deleting the commit does not help: the object stays reachable through the repository history and through forks and caches. Once a key is public, the only safe assumption is that it is already in somebody else's inventory.
How the keys get out
The leak paths are boring and repeatable, which is good news because it means they are enumerable. In roughly descending order of frequency:
- Public and accidentally-public source repositories, including commits that were later reverted but remain in history
- Container images published to public registries with credentials in an ENV instruction or a leftover .aws/credentials layer
- CI/CD configuration and build logs where a secret was echoed by a debug flag or a failing step
- Mobile app bundles and client-side JavaScript, where a developer embedded a key to reach S3 or SES directly
- Infrastructure as code state files and .env files served by a misconfigured web root
- Support tickets, pastebins, wikis, and screenshots shared during troubleshooting
What an attacker does in the first hour
The playbook is consistent enough that you can build detections against it. Step one is identity discovery: sts:GetCallerIdentity, iam:GetUser, iam:ListAttachedUserPolicies. This is cheap, fast, and tells the attacker whether the key is worth keeping. Step two is inventory: s3:ListAllMyBuckets, ec2:DescribeInstances, rds:DescribeDBInstances, secretsmanager:ListSecrets. Step three splits by motive.
- Monetization: launch expensive GPU or compute-optimized instances across many regions for cryptomining, often producing five figure bills within days
- Data theft: bulk GetObject against storage, plus RDS snapshot creation and sharing to an attacker-controlled account
- Persistence: create a new IAM user or access key, attach an admin policy, or add a trust relationship allowing an external account to assume a role
- Evasion: stop CloudTrail logging, delete the trail's S3 bucket contents, or disable GuardDuty in regions the operator does not watch
Detection: what to hunt for now
Do not wait for a bill anomaly. Query CloudTrail for the following patterns across all regions, including the ones you believe are unused, since attackers deliberately work in regions nobody monitors.
- sts:GetCallerIdentity followed within seconds by iam:ListAttachedUserPolicies from the same key, a strong recon signature
- Any API call from an AKIA key whose sourceIPAddress falls outside your known corporate and provider ranges, especially from consumer VPS and residential proxy ASNs
- RunInstances in a region with no prior activity, particularly for GPU or high-vCPU instance families
- CreateUser, CreateAccessKey, AttachUserPolicy, or UpdateAssumeRolePolicy events not tied to an approved change record
- StopLogging, DeleteTrail, PutBucketPolicy on a logging bucket, or DeleteDetector for GuardDuty
- GuardDuty findings in the UnauthorizedAccess:IAMUser and CredentialAccess families, plus AWS Health notifications about exposed credentials
The fix, in priority order
AWS attaches a quarantine policy to IAM users whose keys it detects in public, but that detection is not comprehensive and it is not a control you should depend on. Treat it as a backstop that occasionally saves you, not as coverage.
- Inventory every AKIA key in every account using IAM credential reports, then disable anything unused for 90 days and everything whose owner cannot be identified
- Eliminate long-lived keys where a role will do: instance profiles for EC2, IRSA for EKS, task roles for ECS, and IAM Roles Anywhere or OIDC federation for CI/CD and on-prem workloads
- Replace human IAM users with identity center federation so console and CLI access is short-lived and tied to your IdP
- Apply service control policies at the organization level that deny access from outside expected regions and deny logging and GuardDuty changes for everything except a break-glass role
- Turn on secret scanning with push protection across every repository, and add a pre-commit hook so the block happens on the developer's machine
- Set an aggressive rotation policy for the keys you truly cannot remove, and alert on any key older than the policy
Rotation is not remediation — Deactivating a leaked key stops future use of that key. It does not undo what was done with it. If a key was exposed, review CloudTrail from the earliest possible exposure date, not from the date you noticed, and specifically check for IAM principals created, role trust policies modified, snapshots shared to unknown account IDs, and Lambda functions or EventBridge rules you did not author. Persistence planted with an admin key outlives the key itself.
The uncomfortable part of this research is how little skill it required. Somebody scraped public sources, called a free API to test each string, and ended up holding administrative control over other people's production environments. Every organization running AWS should assume at least one of its keys is discoverable and should be able to answer, today, how many long-lived keys exist, who owns them, and what each one can do.
Originally published on RedEye Threat Intelligence.
Top comments (0)